diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..5870c34 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{py,java,gradle}] +indent_size = 4 + +[*.md] +trim_trailing_whitespace = false diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..62a48a6 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,14 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: monthly + groups: + github-actions: + patterns: ["*"] + + - package-ecosystem: docker-compose + directory: /keycloak + schedule: + interval: monthly diff --git a/.github/workflows/_gradle-ci.yml b/.github/workflows/_gradle-ci.yml new file mode 100644 index 0000000..774af0c --- /dev/null +++ b/.github/workflows/_gradle-ci.yml @@ -0,0 +1,31 @@ +name: _gradle-ci + +on: + workflow_call: + inputs: + working-directory: + type: string + required: true + +permissions: + contents: read + +jobs: + build: + name: Gradle build + runs-on: ubuntu-latest + timeout-minutes: 20 + defaults: + run: + working-directory: ${{ inputs.working-directory }} + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-java@v6 + with: + distribution: temurin + java-version: "21" + + - uses: gradle/actions/setup-gradle@v6 + + - run: ./gradlew build diff --git a/.github/workflows/_node-ci.yml b/.github/workflows/_node-ci.yml new file mode 100644 index 0000000..b2a348e --- /dev/null +++ b/.github/workflows/_node-ci.yml @@ -0,0 +1,41 @@ +name: _node-ci + +on: + workflow_call: + inputs: + working-directory: + type: string + required: true + +permissions: + contents: read + +jobs: + ci: + name: Build and check + runs-on: ubuntu-latest + timeout-minutes: 20 + defaults: + run: + working-directory: ${{ inputs.working-directory }} + env: + NX_DAEMON: "false" + NX_NO_CLOUD: "true" + steps: + - uses: actions/checkout@v7 + + - uses: pnpm/action-setup@v6 + with: + package_json_file: ${{ inputs.working-directory }}/package.json + + - uses: actions/setup-node@v7 + with: + node-version-file: ${{ inputs.working-directory }}/.nvmrc + cache: pnpm + cache-dependency-path: ${{ inputs.working-directory }}/pnpm-lock.yaml + + - run: pnpm install --frozen-lockfile + - run: pnpm run --if-present typecheck + - run: pnpm run --if-present lint + - run: pnpm run --if-present test + - run: pnpm run build diff --git a/.github/workflows/_vercel-deploy.yml b/.github/workflows/_vercel-deploy.yml new file mode 100644 index 0000000..73a4ba9 --- /dev/null +++ b/.github/workflows/_vercel-deploy.yml @@ -0,0 +1,63 @@ +name: _vercel-deploy + +on: + workflow_call: + inputs: + working-directory: + type: string + required: true + secrets: + VERCEL_ORG_ID: + required: false + VERCEL_PROJECT_ID: + required: false + VERCEL_TOKEN: + required: false + +permissions: + contents: read + +jobs: + deploy: + name: Deploy to Vercel + if: >- + github.repository == 'p2-inc/examples' && + github.actor != 'dependabot[bot]' && + (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) + runs-on: ubuntu-latest + timeout-minutes: 20 + defaults: + run: + working-directory: ${{ inputs.working-directory }} + env: + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} + DEPLOY_TARGET: ${{ (github.event_name == 'push' && github.ref == 'refs/heads/main') && 'production' || 'preview' }} + steps: + - uses: actions/checkout@v7 + + - uses: pnpm/action-setup@v6 + with: + package_json_file: ${{ inputs.working-directory }}/package.json + + - uses: actions/setup-node@v7 + with: + node-version-file: ${{ inputs.working-directory }}/.nvmrc + cache: pnpm + cache-dependency-path: ${{ inputs.working-directory }}/pnpm-lock.yaml + + - run: pnpm install --frozen-lockfile + + - run: npm install --global vercel@59 + + - name: Pull Vercel project settings + run: vercel pull --yes --environment="$DEPLOY_TARGET" --token="$VERCEL_TOKEN" + + - name: Build + run: vercel build ${{ env.DEPLOY_TARGET == 'production' && '--prod' || '' }} --token="$VERCEL_TOKEN" + + - name: Deploy + run: | + url=$(vercel deploy --prebuilt ${{ env.DEPLOY_TARGET == 'production' && '--prod' || '' }} --token="$VERCEL_TOKEN") + echo "Deployed to Vercel ($DEPLOY_TARGET): $url" >> "$GITHUB_STEP_SUMMARY" diff --git a/.github/workflows/multitenant.yml b/.github/workflows/multitenant.yml new file mode 100644 index 0000000..b38e36c --- /dev/null +++ b/.github/workflows/multitenant.yml @@ -0,0 +1,27 @@ +name: Multitenant (Nx) + +on: + push: + branches: [main] + paths: + - "multitenant/**" + - ".github/workflows/multitenant.yml" + pull_request: + branches: [main] + paths: + - "multitenant/**" + - ".github/workflows/multitenant.yml" + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + ci: + uses: ./.github/workflows/_node-ci.yml + with: + working-directory: multitenant diff --git a/.gitignore b/.gitignore index fd2505d..cd7641c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,21 +4,38 @@ node_modules .pnp .pnp.js +.pnpm-store # testing coverage # production build +dist +.next +.nuxt +.output +.svelte-kit +.react-router +.angular +.nx/cache +.nx/workspace-data +*.tsbuildinfo +.vercel +__pycache__ +*.py[cod] +.venv +*.sqlite3 +.gradle # misc .DS_Store +.env .env.local -.env.development.local -.env.test.local -.env.production.local +.env.*.local .env.production npm-debug.log* yarn-debug.log* -yarn-error.log* \ No newline at end of file +yarn-error.log* +pnpm-debug.log* diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..a45fd52 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +24 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..dc30f84 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,62 @@ +# Contributing + +Examples are read, copied and pasted more than they are run, so they favour clarity over cleverness and follow the same conventions as Phase Two's own apps. + +## Structure + +- One standalone folder per example. Nothing is shared between examples at build time: each has its own lockfile, config and assets, so copying the folder is enough to run it. +- Keep folder paths stable. The tutorials on [phasetwo.io](https://phasetwo.io/blog) link to them. +- Each example has its own workflow in `.github/workflows`, which calls the shared `_node-ci.yml`, `_vercel-deploy.yml` or `_gradle-ci.yml`. Its `paths` filter lists the example folder and the workflow file itself. + +## JavaScript and TypeScript examples + +| Topic | Convention | +| --------------- | ----------------------------------------------------------------------------------------------------------- | +| Runtime | Node.js 24: `.nvmrc` and `"engines": { "node": "24.x" }` | +| Package manager | pnpm, pinned with `"packageManager"`. Only `pnpm-lock.yaml` is committed. | +| Language | TypeScript, `strict`, the framework's own tsconfig | +| Scripts | `dev`, `build`, `preview` or `start`, `typecheck`, `lint`, `format`, and `test` when there are tests | +| Styling | Tailwind CSS 4, configured in CSS (`@import "tailwindcss"` and an `@theme` block). No `tailwind.config.js`. | +| Lint and format | ESLint flat config from the framework's preset, Prettier with `prettier-plugin-tailwindcss` | +| Configuration | Public settings in env files; secrets only in the environment, never in git | + +Environment variables: + +- Vite SPAs commit a `.env` with the public settings of the hosted demo realm (`VITE_OIDC_ISSUER_URI`, `VITE_OIDC_CLIENT_ID`) and a `.env.local.sample` for the local Keycloak. Copy it to `.env.local`, which is ignored by git. +- Server-side examples commit only `.env.example`, pointing at the local Keycloak. + +Local ports, so examples match the Keycloak clients in [`keycloak/realms/p2examples.json`](./keycloak/realms/p2examples.json): + +| Port | Examples | +| ----------- | -------------------------------------------------------------------------- | +| 3000 | React, Vue, Nuxt, Next.js, React Router (Remix), SvelteKit | +| 4200 / 4201 | Angular, Spring Boot's Angular client, multitenant zoo / aquarium | +| 8000 | Django | +| 8080 | the local Keycloak, or the Spring Boot API (with its own Keycloak on 8888) | +| 8081 | SAML service provider | + +## Authentication + +- Use the authorization code flow with PKCE. Never ship a client secret in browser code. +- Log out through Keycloak so the SSO session ends, not only the local session. +- Keep tokens out of the browser in server-side examples; show decoded claims instead. +- Let the library refresh tokens; no `setInterval` refresh loops. + +## Look and feel + +All examples share the same page, so they are easy to compare and one smoke test covers them all: + +- the Phase Two background (`home-bg.webp`, `home-bg-mobile.webp`) and logo, and the `p2blue`, `p2gray`, `p2grad` and `p2dark` colours; +- a header linking to phasetwo.io and to the example's own folder on GitHub; +- the status line "Your current status is:" followed by "Not authenticated." or "Authenticated", with "Log in" and "Log out" buttons; +- decoded "Access token (decoded)" and "ID token (decoded)" panels; +- the Docs, Github, Blog and Contact footer. + +Icons are small inline SVG components in each example, so they inherit the text colour. No icon library. + +## Before opening a pull request + +- `pnpm install --frozen-lockfile`, `pnpm typecheck`, `pnpm lint`, `pnpm test` and `pnpm build` pass on Node.js 24 (or `./gradlew build`, or `python manage.py test`). +- Logging in and out works against the local Keycloak. For the JavaScript examples, run [`tools/e2e-smoke`](./tools/e2e-smoke). +- No secrets are committed. +- The pull request description has a **Docs drift** section listing the phasetwo.io tutorials and docs pages whose code snippets no longer match the example. diff --git a/README.md b/README.md index 4a94919..9d5a555 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,45 @@ # Phase Two Framework Examples -This is a repo for code examples showing how to integrate Keycloak with various frameworks. +This is a repo for code examples showing how to integrate Keycloak with various frameworks. Every example is a standalone project: copy its folder and it runs on its own. ## Frameworks -| Framework | Code | Live | Tutorial | -| ---------------------- | :-----------------------------------------: | :----------------------------------------------------------: | :---------------------------------------------------------------------------: | -| React (oidc-client-ts) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/reactjs/oidc-client-ts) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-react-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-managemenet-and-sso-for-reactjs/) | -| React (oidc-spa) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/reactjs/oidc-spa) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-react-oidcspa-example.vercel.app/) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/keycloak-oidc-spa-phasetwo) | -| Next.js | [πŸ§‘β€πŸ’»πŸ“](./frameworks/nextjs/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-nextjs-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-managemenet-and-sso-for-nextjs/) | -| Remix | [πŸ§‘β€πŸ’»πŸ“](./frameworks/remix/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-remix-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-management-and-sso-for-remix/) | -| Vue | [πŸ§‘β€πŸ’»πŸ“](./frameworks/vue/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-vue-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-managemenet-and-sso-for-vue/) | -| Nuxt (keycloak-js) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/nuxt/keycloak-js/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-nuxt-keycloakjs-example.vercel.app/) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-managemenet-and-sso-for-nuxt/) | -| Nuxt (oidc-client-ts) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/nuxt/oidc-client-ts/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-nuxt-oidc-example.vercel.app/) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-managemenet-and-sso-for-nuxt/) | -| Sveltekit | [πŸ§‘β€πŸ’»πŸ“](./frameworks/sveltekit/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-sveltekit-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-management-and-sso-for-sveltekit/) | -| Angular | [πŸ§‘β€πŸ’»πŸ“](./frameworks/angular/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-angular-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-management-and-sso-for-angular/) | -| Django | [πŸ§‘β€πŸ’»πŸ“](./frameworks/django/) | πŸ‘©β€πŸ’»βš’οΈ | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/secure-django/) | -| SpringBoot + Angular | [πŸ§‘β€πŸ’»πŸ“](./frameworks/spring-boot-keycloak/) | πŸ‘©β€πŸ’»βš’οΈ | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/secure-spring-boot/) | +| Framework | Code | Live | Tutorial | Local port | +| ------------------------------------ | :-------------------------------------------: | :----------------------------------------------------------: | :-----------------------------------------------------------------------------------------: | :---------: | +| React (oidc-client-ts) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/reactjs/oidc-client-ts) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-react-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-managemenet-and-sso-for-reactjs/) | 3000 | +| React (oidc-spa) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/reactjs/oidc-spa) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-react-oidcspa-example.vercel.app/) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/keycloak-oidc-spa-phasetwo) | 3000 | +| React (oidc-spa tutorial starter) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/reactjs/oidc-spa-starter) | β€” | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/keycloak-oidc-spa-phasetwo) | 3000 | +| Next.js (NextAuth.js) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/nextjs/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-nextjs-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-managemenet-and-sso-for-nextjs/) | 3000 | +| Remix (remix-auth) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/remix/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-remix-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-management-and-sso-for-remix/) | 3000 | +| Vue (oidc-client-ts) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/vue/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-vue-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-managemenet-and-sso-for-vue/) | 3000 | +| Nuxt (keycloak-js) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/nuxt/keycloak-js/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-nuxt-keycloakjs-example.vercel.app/) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-managemenet-and-sso-for-nuxt/) | 3000 | +| Nuxt (oidc-client-ts) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/nuxt/oidc-client-ts/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-nuxt-oidc-example.vercel.app/) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-managemenet-and-sso-for-nuxt/) | 3000 | +| SvelteKit (Auth.js) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/sveltekit/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-sveltekit-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-management-and-sso-for-sveltekit/) | 3000 | +| Angular (angular-oauth2-oidc) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/angular/) | [πŸ‘©β€πŸ’»πŸš€](https://phasetwo-angular-example.vercel.app) | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/instant-user-management-and-sso-for-angular/) | 4200 | +| Django (mozilla-django-oidc) | [πŸ§‘β€πŸ’»πŸ“](./frameworks/django/) | πŸ‘©β€πŸ’»βš’οΈ | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/secure-django/) | 8000 | +| Spring Boot + Angular | [πŸ§‘β€πŸ’»πŸ“](./frameworks/spring-boot-keycloak/) | πŸ‘©β€πŸ’»βš’οΈ | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/secure-spring-boot/) | 8080 / 4200 | +| SAML IdP-initiated SSO (Spring Boot) | [πŸ§‘β€πŸ’»πŸ“](./saml2/idp-initiated/) | πŸ‘©β€πŸ’»βš’οΈ | [πŸ‘©β€πŸ«](https://phasetwo.io/blog/keycloak-saml-identity-provider-idp-initiated-flow-with-okta) | 8081 | ## Multi-tenant -[Demo Apps](./multitenant/README.md) to be used as a starting point for a multi-tenant setup. Uses `nx` to manage the apps and `oidc-spa`. +[Demo Apps](./multitenant/README.md) to be used as a starting point for a multi-tenant setup with [Phase Two Organizations](https://phasetwo.io/docs/organizations/). Uses `nx` to manage the apps and `oidc-spa`. Tutorial: [Implement Multi-Tenancy Applications with Keycloak Organizations](https://phasetwo.io/blog/multi-tenancy-with-keycloak-organizations). + +## Running an example + +Each example's README has its exact steps. They all need: + +- [Node.js 24](https://nodejs.org/) (see `.nvmrc`) and [pnpm](https://pnpm.io/), for the JavaScript examples. With Corepack (`corepack enable`), the pnpm version pinned in each `package.json` is used automatically. +- Python 3.13+ for Django, and a JDK for the Spring Boot examples (Gradle downloads JDK 21 if needed). +- A Keycloak to log in against, either: + - **the hosted demo realm** `https://app.phasetwo.io/auth/realms/p2examples`, which the live demos use, or + - **a local Phase Two Keycloak**: `docker compose -f keycloak/docker-compose.yml up -d --wait` starts one with a pre-configured `p2examples` realm and demo users. See [keycloak/README.md](./keycloak/README.md). Each example has a sample env file for it. + +To use your own [Phase Two](https://phasetwo.io) or Keycloak instance, create the client described in the example's README and point the example at your realm. ## Github Actions -This repo contains actions that deploy all frameworks. Feel free to use, disable, or remove as desired. +Every example has a workflow in [.github/workflows](./.github/workflows) that builds it on pull requests. The examples with a live demo are also deployed to Vercel: a preview deployment for pull requests and a production deployment for `main`. Deployments need the `VERCEL_ORG_ID`, `VERCEL_DEPLOYMENT_TOKEN` and `VERCEL__PROJECT_ID` secrets, and are skipped for forks and Dependabot pull requests. Feel free to use, disable, or remove as desired. + +## Contributing + +See [CONTRIBUTING.md](./CONTRIBUTING.md) for the conventions the examples follow. diff --git a/frameworks/nuxt/README.md b/frameworks/nuxt/README.md new file mode 100644 index 0000000..0ccbabe --- /dev/null +++ b/frameworks/nuxt/README.md @@ -0,0 +1,8 @@ +# Nuxt examples + +| Example | Library | Live demo | +| ---------------------------------- | ---------------------------------------------------------- | --------------------------------------------------- | +| [keycloak-js](./keycloak-js) | [keycloak-js](https://github.com/keycloak/keycloak-js) | https://phasetwo-nuxt-keycloakjs-example.vercel.app | +| [oidc-client-ts](./oidc-client-ts) | [oidc-client-ts](https://github.com/authts/oidc-client-ts) | https://phasetwo-nuxt-oidc-example.vercel.app | + +Both follow the tutorial [Securing Nuxt Apps with Keycloak](https://phasetwo.io/blog/instant-user-managemenet-and-sso-for-nuxt/). diff --git a/frameworks/reactjs/README.md b/frameworks/reactjs/README.md new file mode 100644 index 0000000..ed5d9fa --- /dev/null +++ b/frameworks/reactjs/README.md @@ -0,0 +1,7 @@ +# React examples + +| Example | Library | Live demo | +| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------- | +| [oidc-client-ts](./oidc-client-ts) | [react-oidc-context](https://github.com/authts/react-oidc-context) and [oidc-client-ts](https://github.com/authts/oidc-client-ts) | https://phasetwo-react-example.vercel.app | +| [oidc-spa](./oidc-spa) | [oidc-spa](https://www.oidc-spa.dev/) | https://phasetwo-react-oidcspa-example.vercel.app | +| [oidc-spa-starter](./oidc-spa-starter) | none yet: the starting point of the [oidc-spa tutorial](https://phasetwo.io/blog/keycloak-oidc-spa-phasetwo) | β€” | diff --git a/keycloak/README.md b/keycloak/README.md new file mode 100644 index 0000000..485a2f1 --- /dev/null +++ b/keycloak/README.md @@ -0,0 +1,55 @@ +# Local Phase Two Keycloak + +A throwaway [Phase Two Keycloak](https://github.com/p2-inc/phasetwo-containers) with a `p2examples` realm, so every example in this repo can be run end to end on your machine. The realm uses the same client IDs as the hosted demo realm (`https://app.phasetwo.io/auth/realms/p2examples`), so switching an example between the two only changes its issuer URL (and, for server-side examples, the client secret). + +## Start and stop + +Run these from the repository root. You need Docker with the Compose plugin; the standalone `docker-compose` command works the same way. + +```sh +docker compose -f keycloak/docker-compose.yml up -d --wait # Keycloak + realm +docker compose -f keycloak/docker-compose.yml --profile orgs up -d --wait # ...plus demo organizations (for /multitenant) +docker compose -f keycloak/docker-compose.yml down # stop; everything is reset +``` + +| What | Value | +| --------------------------------------- | ------------------------------------------------------- | +| Issuer (use in the examples' env files) | `http://localhost:8080/auth/realms/p2examples` | +| Admin console | http://localhost:8080/auth/admin β€” `admin` / `admin` | +| Demo users | `demo` / `demo`, `jane` / `jane`, `jacques` / `jacques` | + +Nothing is persisted: `down` followed by `up` gives you a fresh realm, re-imported from [`realms/p2examples.json`](./realms/p2examples.json). + +## Clients + +Every client allows its local redirect URIs, `+` as web origin (CORS for the redirect URIs' origins) and `+` as post-logout redirect URIs. Public clients require PKCE (S256). + +| Client ID | Type | Local redirect URIs | Used by | +| ----------------------------- | --------------- | ---------------------------------------------------- | -------------------------------- | +| `reactjs-example` | public | `http://localhost:3000/*` | `frameworks/reactjs/*` | +| `vue-example` | public | `http://localhost:3000/*` | `frameworks/vue` | +| `nuxt-example` | public | `http://localhost:3000/*` | `frameworks/nuxt/keycloak-js` | +| `nuxt-oidc-client-ts-example` | public | `http://localhost:3000/*` | `frameworks/nuxt/oidc-client-ts` | +| `angular` | public | `http://localhost:4200/*` | `frameworks/angular` | +| `zoo` | public | `http://localhost:4200/*` | `multitenant/apps/zoo` | +| `aquarium` | public | `http://localhost:4201/*` | `multitenant/apps/aquarium` | +| `nextjs` | confidential | `http://localhost:3000/*` | `frameworks/nextjs` | +| `remix` | confidential | `http://localhost:3000/*` | `frameworks/remix` | +| `sveltekit` | confidential | `http://localhost:3000/*` | `frameworks/sveltekit` | +| `django` | confidential | `http://localhost:8000/*`, `http://127.0.0.1:8000/*` | `frameworks/django` | +| `seed-cli` | service account | β€” | `seed/seed-orgs.mjs` | + +Confidential clients use the secret `-local-dev-secret` (for example `nextjs-local-dev-secret`). **These secrets, and the demo passwords, exist only for this local container.** Never reuse them anywhere else. + +The Spring Boot and SAML examples keep their own Keycloak setup (`frameworks/spring-boot-keycloak/docker-compose.yml` on port 8888, `saml2/idp-initiated`), because their tutorials use different realms. + +## Organizations (for `/multitenant`) + +The `orgs` profile runs [`seed/seed-orgs.mjs`](./seed/seed-orgs.mjs) once Keycloak is healthy. It uses the Phase Two Organizations API to create the setup from [Implement Multi-Tenancy Applications with Keycloak Organizations](https://phasetwo.io/blog/multi-tenancy-with-keycloak-organizations): + +| Organization | `jane` | `jacques` | +| ------------ | ----------------- | ---------- | +| `california` | `zoo` | `aquarium` | +| `newyork` | `zoo`, `aquarium` | `aquarium` | + +Both users are members of both organizations; the roles decide which app (zoo or aquarium) they can use in each tenant. The script can also run on the host: `KEYCLOAK_URL=http://localhost:8080/auth node keycloak/seed/seed-orgs.mjs`. diff --git a/keycloak/docker-compose.yml b/keycloak/docker-compose.yml new file mode 100644 index 0000000..9bb514a --- /dev/null +++ b/keycloak/docker-compose.yml @@ -0,0 +1,39 @@ +name: p2-examples-keycloak + +services: + keycloak: + image: quay.io/phasetwo/phasetwo-keycloak:26.6 + command: ["start-dev", "--import-realm"] + environment: + KC_BOOTSTRAP_ADMIN_USERNAME: admin + KC_BOOTSTRAP_ADMIN_PASSWORD: admin + KC_HTTP_RELATIVE_PATH: /auth + KC_HEALTH_ENABLED: "true" + ports: + - "8080:8080" + volumes: + - ./realms:/opt/keycloak/data/import:ro + healthcheck: + test: + [ + "CMD", + "bash", + "-c", + "exec 3<>/dev/tcp/127.0.0.1/9000 && printf 'GET /auth/health/ready HTTP/1.0\\r\\nHost: localhost\\r\\n\\r\\n' >&3 && grep -q UP <&3", + ] + interval: 5s + timeout: 5s + retries: 60 + start_period: 20s + + seed-orgs: + profiles: ["orgs"] + image: node:24-alpine + depends_on: + keycloak: + condition: service_healthy + environment: + KEYCLOAK_URL: http://keycloak:8080/auth + volumes: + - ./seed:/seed:ro + command: ["node", "/seed/seed-orgs.mjs"] diff --git a/keycloak/realms/p2examples.json b/keycloak/realms/p2examples.json new file mode 100644 index 0000000..019874f --- /dev/null +++ b/keycloak/realms/p2examples.json @@ -0,0 +1,270 @@ +{ + "realm": "p2examples", + "displayName": "Phase Two Examples (local)", + "enabled": true, + "sslRequired": "external", + "registrationAllowed": true, + "loginWithEmailAllowed": true, + "duplicateEmailsAllowed": false, + "resetPasswordAllowed": false, + "clients": [ + { + "clientId": "reactjs-example", + "name": "React examples (oidc-client-ts, oidc-spa)", + "enabled": true, + "publicClient": true, + "standardFlowEnabled": true, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "rootUrl": "http://localhost:3000", + "baseUrl": "/", + "redirectUris": ["http://localhost:3000/*"], + "webOrigins": ["+"], + "attributes": { + "pkce.code.challenge.method": "S256", + "post.logout.redirect.uris": "+" + } + }, + { + "clientId": "vue-example", + "name": "Vue example (oidc-client-ts)", + "enabled": true, + "publicClient": true, + "standardFlowEnabled": true, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "rootUrl": "http://localhost:3000", + "baseUrl": "/", + "redirectUris": ["http://localhost:3000/*"], + "webOrigins": ["+"], + "attributes": { + "pkce.code.challenge.method": "S256", + "post.logout.redirect.uris": "+" + } + }, + { + "clientId": "nuxt-example", + "name": "Nuxt example (keycloak-js)", + "enabled": true, + "publicClient": true, + "standardFlowEnabled": true, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "rootUrl": "http://localhost:3000", + "baseUrl": "/", + "redirectUris": ["http://localhost:3000/*"], + "webOrigins": ["+"], + "attributes": { + "pkce.code.challenge.method": "S256", + "post.logout.redirect.uris": "+" + } + }, + { + "clientId": "nuxt-oidc-client-ts-example", + "name": "Nuxt example (oidc-client-ts)", + "enabled": true, + "publicClient": true, + "standardFlowEnabled": true, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "rootUrl": "http://localhost:3000", + "baseUrl": "/", + "redirectUris": ["http://localhost:3000/*"], + "webOrigins": ["+"], + "attributes": { + "pkce.code.challenge.method": "S256", + "post.logout.redirect.uris": "+" + } + }, + { + "clientId": "angular", + "name": "Angular example (angular-oauth2-oidc)", + "enabled": true, + "publicClient": true, + "standardFlowEnabled": true, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "rootUrl": "http://localhost:4200", + "baseUrl": "/", + "redirectUris": ["http://localhost:4200/*"], + "webOrigins": ["+"], + "attributes": { + "pkce.code.challenge.method": "S256", + "post.logout.redirect.uris": "+" + } + }, + { + "clientId": "zoo", + "name": "Multitenant example: zoo app (oidc-spa)", + "enabled": true, + "publicClient": true, + "standardFlowEnabled": true, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "rootUrl": "http://localhost:4200", + "baseUrl": "/", + "redirectUris": ["http://localhost:4200/*"], + "webOrigins": ["+"], + "attributes": { + "pkce.code.challenge.method": "S256", + "post.logout.redirect.uris": "+" + } + }, + { + "clientId": "aquarium", + "name": "Multitenant example: aquarium app (oidc-spa)", + "enabled": true, + "publicClient": true, + "standardFlowEnabled": true, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "rootUrl": "http://localhost:4201", + "baseUrl": "/", + "redirectUris": ["http://localhost:4201/*"], + "webOrigins": ["+"], + "attributes": { + "pkce.code.challenge.method": "S256", + "post.logout.redirect.uris": "+" + } + }, + { + "clientId": "nextjs", + "name": "Next.js example (next-auth)", + "enabled": true, + "publicClient": false, + "clientAuthenticatorType": "client-secret", + "secret": "nextjs-local-dev-secret", + "standardFlowEnabled": true, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "rootUrl": "http://localhost:3000", + "baseUrl": "/", + "redirectUris": ["http://localhost:3000/*"], + "webOrigins": ["+"], + "attributes": { + "post.logout.redirect.uris": "+" + } + }, + { + "clientId": "remix", + "name": "React Router example, formerly Remix (remix-auth)", + "enabled": true, + "publicClient": false, + "clientAuthenticatorType": "client-secret", + "secret": "remix-local-dev-secret", + "standardFlowEnabled": true, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "rootUrl": "http://localhost:3000", + "baseUrl": "/", + "redirectUris": ["http://localhost:3000/*"], + "webOrigins": ["+"], + "attributes": { + "post.logout.redirect.uris": "+" + } + }, + { + "clientId": "sveltekit", + "name": "SvelteKit example (Auth.js)", + "enabled": true, + "publicClient": false, + "clientAuthenticatorType": "client-secret", + "secret": "sveltekit-local-dev-secret", + "standardFlowEnabled": true, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "rootUrl": "http://localhost:3000", + "baseUrl": "/", + "redirectUris": ["http://localhost:3000/*"], + "webOrigins": ["+"], + "attributes": { + "post.logout.redirect.uris": "+" + } + }, + { + "clientId": "django", + "name": "Django example (mozilla-django-oidc)", + "enabled": true, + "publicClient": false, + "clientAuthenticatorType": "client-secret", + "secret": "django-local-dev-secret", + "standardFlowEnabled": true, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "rootUrl": "http://localhost:8000", + "baseUrl": "/", + "redirectUris": ["http://localhost:8000/*", "http://127.0.0.1:8000/*"], + "webOrigins": ["+"], + "attributes": { + "post.logout.redirect.uris": "+" + } + }, + { + "clientId": "seed-cli", + "name": "Organization seed for the multitenant example", + "enabled": true, + "publicClient": false, + "clientAuthenticatorType": "client-secret", + "secret": "seed-cli-local-dev-secret", + "standardFlowEnabled": false, + "directAccessGrantsEnabled": false, + "implicitFlowEnabled": false, + "serviceAccountsEnabled": true + } + ], + "users": [ + { + "username": "demo", + "email": "demo@example.com", + "firstName": "Demo", + "lastName": "User", + "enabled": true, + "emailVerified": true, + "credentials": [ + { + "type": "password", + "value": "demo", + "temporary": false + } + ] + }, + { + "username": "jane", + "email": "jane@example.com", + "firstName": "Jane", + "lastName": "Goodall", + "enabled": true, + "emailVerified": true, + "credentials": [ + { + "type": "password", + "value": "jane", + "temporary": false + } + ] + }, + { + "username": "jacques", + "email": "jacques@example.com", + "firstName": "Jacques", + "lastName": "Cousteau", + "enabled": true, + "emailVerified": true, + "credentials": [ + { + "type": "password", + "value": "jacques", + "temporary": false + } + ] + }, + { + "username": "service-account-seed-cli", + "enabled": true, + "serviceAccountClientId": "seed-cli", + "clientRoles": { + "realm-management": ["realm-admin"] + } + } + ] +} diff --git a/keycloak/seed/seed-orgs.mjs b/keycloak/seed/seed-orgs.mjs new file mode 100644 index 0000000..74bba2c --- /dev/null +++ b/keycloak/seed/seed-orgs.mjs @@ -0,0 +1,102 @@ +const KEYCLOAK_URL = process.env.KEYCLOAK_URL ?? "http://localhost:8080/auth"; +const REALM = "p2examples"; +const CLIENT_ID = "seed-cli"; +const CLIENT_SECRET = "seed-cli-local-dev-secret"; + +const organizations = [ + { + name: "california", + displayName: "California", + roles: ["zoo", "aquarium"], + members: { jane: ["zoo"], jacques: ["aquarium"] }, + }, + { + name: "newyork", + displayName: "New York", + roles: ["zoo", "aquarium"], + members: { jane: ["zoo", "aquarium"], jacques: ["aquarium"] }, + }, +]; + +const base = `${KEYCLOAK_URL}/realms/${REALM}`; + +async function getToken() { + const response = await fetch(`${base}/protocol/openid-connect/token`, { + method: "POST", + body: new URLSearchParams({ + grant_type: "client_credentials", + client_id: CLIENT_ID, + client_secret: CLIENT_SECRET, + }), + }); + if (!response.ok) { + throw new Error( + `Token request failed: ${response.status} ${await response.text()}`, + ); + } + return (await response.json()).access_token; +} + +const token = await getToken(); + +async function api(method, url, body) { + const response = await fetch(url, { + method, + headers: { + Authorization: `Bearer ${token}`, + ...(body ? { "Content-Type": "application/json" } : {}), + }, + body: body ? JSON.stringify(body) : undefined, + }); + if (!response.ok && response.status !== 409) { + throw new Error( + `${method} ${url} failed: ${response.status} ${await response.text()}`, + ); + } + return response; +} + +async function findUserId(username) { + const response = await api( + "GET", + `${KEYCLOAK_URL}/admin/realms/${REALM}/users?exact=true&username=${encodeURIComponent(username)}`, + ); + const [user] = await response.json(); + if (!user) throw new Error(`User "${username}" not found in realm ${REALM}`); + return user.id; +} + +async function findOrCreateOrganization({ name, displayName }) { + const search = await api( + "GET", + `${base}/orgs?search=${encodeURIComponent(name)}`, + ); + const existing = (await search.json()).find((org) => org.name === name); + if (existing) return existing.id; + + const created = await api("POST", `${base}/orgs`, { name, displayName }); + const location = created.headers.get("Location"); + if (!location) + throw new Error( + `Organization "${name}" was created without a Location header`, + ); + return location.split("/").pop(); +} + +for (const org of organizations) { + const orgId = await findOrCreateOrganization(org); + + for (const role of org.roles) { + await api("POST", `${base}/orgs/${orgId}/roles`, { name: role }); + } + + for (const [username, roles] of Object.entries(org.members)) { + const userId = await findUserId(username); + await api("PUT", `${base}/orgs/${orgId}/members/${userId}`); + for (const role of roles) { + await api("PUT", `${base}/orgs/${orgId}/roles/${role}/users/${userId}`); + } + } + + console.log(`Seeded organization "${org.name}" (${orgId})`); +} diff --git a/multitenant/.gitignore b/multitenant/.gitignore index 56c6400..68030ea 100644 --- a/multitenant/.gitignore +++ b/multitenant/.gitignore @@ -1,44 +1,26 @@ -# See http://help.github.com/ignore-files/ for more about ignoring files. - -# compiled output +node_modules dist tmp /out-tsc +/coverage +*.tsbuildinfo +vite.config.*.timestamp* -# dependencies -node_modules +!.env +.env.local +.env.*.local -# IDEs and editors -/.idea -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace +.nx/cache +.nx/workspace-data +.nx/polygraph +.nx/self-healing +.nx/migrate-runs + +.claude/worktrees +.claude/settings.local.json -# IDE - VSCode +/.idea .vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json !.vscode/extensions.json - -# misc -/.sass-cache -/connect.lock -/coverage -/libpeerconnection.log -npm-debug.log -yarn-error.log -testem.log -/typings - -# System Files .DS_Store Thumbs.db - -.nx/cache -.nx/workspace-data - -vite.config.*.timestamp* \ No newline at end of file diff --git a/multitenant/.nvmrc b/multitenant/.nvmrc new file mode 100644 index 0000000..a45fd52 --- /dev/null +++ b/multitenant/.nvmrc @@ -0,0 +1 @@ +24 diff --git a/multitenant/.prettierignore b/multitenant/.prettierignore index e26f0b3..b208ce8 100644 --- a/multitenant/.prettierignore +++ b/multitenant/.prettierignore @@ -1,5 +1,7 @@ -# Add files here to ignore them from prettier formatting /dist /coverage /.nx/cache -/.nx/workspace-data \ No newline at end of file +/.nx/workspace-data +.nx/self-healing +pnpm-lock.yaml +libs/phasetwo-orgs-api/src/lib diff --git a/multitenant/.prettierrc b/multitenant/.prettierrc index 544138b..02d01e1 100644 --- a/multitenant/.prettierrc +++ b/multitenant/.prettierrc @@ -1,3 +1,5 @@ { - "singleQuote": true + "singleQuote": true, + "plugins": ["prettier-plugin-tailwindcss"], + "tailwindStylesheet": "./apps/zoo/src/styles.css" } diff --git a/multitenant/.vscode/extensions.json b/multitenant/.vscode/extensions.json index 97e81d4..cbbc2f7 100644 --- a/multitenant/.vscode/extensions.json +++ b/multitenant/.vscode/extensions.json @@ -2,6 +2,7 @@ "recommendations": [ "nrwl.angular-console", "esbenp.prettier-vscode", - "firsttris.vscode-jest-runner" + "dbaeumer.vscode-eslint", + "vitest.explorer" ] } diff --git a/multitenant/README.md b/multitenant/README.md index 0dbdc08..1c6bece 100644 --- a/multitenant/README.md +++ b/multitenant/README.md @@ -1,50 +1,110 @@ -# Multitenant +# Phase Two multitenant example: Keycloak Organizations -Update values in the following locations: +Two React apps, **Zoo** and **Aquarium**, share one Keycloak realm and use [Phase Two Organizations](https://phasetwo.io/product/organizations/) for multi-tenancy: -* In `@multitenant/api-manager/src/lib/api-manager.ts` update `BASE_PATH` and `REALM` to your associated Keycloak instance and realm name. -* In both `@multitenant/zoo/src/main.tsx` and `@multitenant/aquarium/src/main.tsx` update `client` to be your associated client from the Keycloak instance. +- each **organization** is a tenant (`california`, `newyork`); +- each organization has one **role per app** (`zoo`, `aquarium`); +- users are **members** of the organizations they belong to, and the roles they hold in an organization decide which apps they can use for that tenant. -## Run tasks +Both apps log users in with [oidc-spa](https://www.oidc-spa.dev/) and call the Organizations API endpoint [`GET /{realm}/orgs/me`](https://phasetwo.io/api/get-me/) with the user's access token. They list the user's organizations with their roles, and show for each one whether it gives access to the current app. -To run the dev server for your app, use: +The tutorial [Implement Multi-Tenancy Applications with Keycloak Organizations](https://phasetwo.io/blog/multi-tenancy-with-keycloak-organizations) explains the concepts and the Keycloak setup. -```sh -npx nx serve zoo -``` +## What's inside + +This is an [Nx](https://nx.dev) workspace with two apps and three libraries: + +| Path | What it is | +| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | +| [`apps/zoo`](./apps/zoo), [`apps/aquarium`](./apps/aquarium) | The two apps, built with Vite, React 19 and Tailwind CSS 4. Each one has its own Keycloak client. | +| [`libs/api-manager`](./libs/api-manager) | `createOrgsApi()`, which calls the Organizations API with a fresh access token on every request. | +| [`libs/phasetwo-orgs-api`](./libs/phasetwo-orgs-api) | The Organizations API client, generated from the Phase Two OpenAPI spec. | +| [`libs/ui-shared`](./libs/ui-shared) | The page both apps share: layout, footer, icons and the organization cards. | + +In each app: + +- `src/oidc.ts` creates the oidc-spa utilities (`useOidc`, `getOidc`, `OidcInitializationGate`) and bootstraps them from the environment variables below. +- `vite.config.ts` adds the oidc-spa Vite plugin, which starts oidc-spa before the app loads and hardens the page against token theft. +- `src/orgs-api.ts` creates the Organizations API client. It gets the access token from oidc-spa for each request, so the token is always fresh. +- `src/app/auth.tsx` shows the login state, the Log in / Log out buttons and the organizations. `appRole` is the organization role that grants access to the app. -To create a production bundle: +The apps import the libraries from source through the path aliases in [`tsconfig.base.json`](./tsconfig.base.json) (`@multitenant/api-manager`, `@multitenant/phasetwo-orgs-api`, `@multitenant/ui-shared`), which Vite resolves with `resolve.tsconfigPaths`. The libraries have no build step of their own. + +## Run it with the local Keycloak + +You need Node.js 24, pnpm and Docker. From the repository root, start the [local Phase Two Keycloak](../keycloak/README.md) with the demo organizations: ```sh -npx nx build zoo +docker compose -f keycloak/docker-compose.yml --profile orgs up -d --wait ``` -To see all available targets to run for a project, run: +Then, in this folder: ```sh -npx nx show project zoo +pnpm install +pnpm dev ``` -These targets are either [inferred automatically](https://nx.dev/concepts/inferred-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) or defined in the `project.json` or `package.json` files. +`pnpm dev` starts both apps: Zoo on and Aquarium on . `pnpm dev:zoo` and `pnpm dev:aquarium` start only one. -[More about running tasks in the docs »](https://nx.dev/features/run-tasks?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) +Log in as `jane` / `jane` or `jacques` / `jacques` in each app to see the difference. Both users are members of both organizations, but they don't have the same roles: -## Add new projects +| User | California | New York | +| --------- | ---------- | ----------------- | +| `jane` | `zoo` | `zoo`, `aquarium` | +| `jacques` | `aquarium` | `aquarium` | -While you could add new projects to your workspace manually, you might want to leverage [Nx plugins](https://nx.dev/concepts/nx-plugins?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) and their [code generation](https://nx.dev/features/generate-code?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) feature. +Jane can use Zoo for both tenants and Aquarium only for New York. Jacques can use Aquarium for both tenants and Zoo for neither. -Use the plugin's generator to create new projects. +## Configuration -To generate a new application, use: +Each app reads its settings from its own `.env`: -```sh -npx nx g @nx/react:app demo -``` +| Variable | Description | Default | +| ---------------------- | ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | +| `VITE_OIDC_ISSUER_URI` | URL of your Keycloak realm. The Organizations API URL and the realm name are derived from it. | `http://localhost:8080/auth/realms/p2examples` | +| `VITE_OIDC_CLIENT_ID` | Client ID of the app's public Keycloak client | `zoo` in `apps/zoo/.env`, `aquarium` in `apps/aquarium/.env` | +| `VITE_OIDC_USE_MOCK` | `true` to replace Keycloak with a mock user, as the tests do. The organizations still need a real Keycloak. | `false` | +| `VITE_OIDC_SPA_DEBUG` | `true` to log oidc-spa's initialization and token lifecycle | `false` | + +`.env` points at the local Keycloak, which has the clients and organizations this example needs. To use another realm, copy `.env.local.sample` to `.env.local` in each app and edit it. `.env.local` is ignored by git. -To generate a new library, use: +## Commands + +Run them in this folder. They go through Nx, which runs the target in every project that has it and caches the results. + +| Command | What it does | +| ------------------------ | ------------------------------------------------------------------------ | +| `pnpm dev` | Starts both apps in development mode | +| `pnpm build` | Builds both apps into `dist/apps/zoo` and `dist/apps/aquarium` | +| `pnpm preview` | Builds both apps and serves the production builds on ports 4200 and 4201 | +| `pnpm typecheck` | Type-checks every project, tests and Vite configs included | +| `pnpm lint` | Lints every project with Nx's ESLint flat configs | +| `pnpm test` | Runs the Vitest tests of every project | +| `pnpm format` | Formats the workspace with Prettier | +| `pnpm generate:orgs-api` | Regenerates the Organizations API client (see below) | + +Nx can also run a single target of a single project, for example `pnpm nx test ui-shared` or `pnpm nx build zoo`. `pnpm nx show project zoo` lists the targets of a project: Nx infers them from its `vite.config.ts`, `eslint.config.mjs` and `tsconfig.json`. + +The tests don't need Keycloak. The apps render with oidc-spa's mock (`VITE_OIDC_USE_MOCK=true`, set in the `test` section of each `vite.config.ts`), `api-manager` checks the requests sent to the Organizations API, and `ui-shared` renders the organization cards with sample data. + +## Regenerate the Organizations API client + +`libs/phasetwo-orgs-api/src/lib` is generated with [OpenAPI Generator](https://openapi-generator.tech) from the [Phase Two OpenAPI spec](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/refs/heads/main/openapi.yaml). To regenerate it, with Java 11 or newer installed: ```sh -npx nx g @nx/react:lib mylib +pnpm generate:orgs-api ``` -You can use `npx nx list` to get a list of installed plugins. Then, run `npx nx list ` to learn about more specific capabilities of a particular plugin. Alternatively, [install Nx Console](https://nx.dev/getting-started/editor-setup?utm_source=nx_project&utm_medium=readme&utm_campaign=nx_projects) to browse plugins and generators in your IDE. +The generator version and options live in [`openapitools.json`](./openapitools.json). [`libs/phasetwo-orgs-api/README.md`](./libs/phasetwo-orgs-api/README.md) explains them. + +## Use your own realm + +Your Keycloak needs the [Phase Two Organizations extension](https://github.com/p2-inc/keycloak-orgs). It is included in [Phase Two's hosted Keycloak](https://phasetwo.io/hosting/) and in the [Phase Two Keycloak image](https://github.com/p2-inc/phasetwo-containers). + +1. Create two OpenID Connect clients, `zoo` and `aquarium`, with client authentication off, the standard flow enabled and `S256` as PKCE method. Set `http://localhost:4200/*` (Zoo) or `http://localhost:4201/*` (Aquarium) as valid redirect URI, and `+` as web origin and as valid post logout redirect URI. The `+` web origin lets the browser call Keycloak's token endpoint and the Organizations API from the app. +2. Create your organizations, for example `california` and `newyork`, each with the roles `zoo` and `aquarium`. +3. Add your users as members of the organizations, and grant each of them the roles of the apps they may use there. +4. In each app, copy `.env.local.sample` to `.env.local` and set your realm's issuer URI and the client ID. + +[`keycloak/seed/seed-orgs.mjs`](../keycloak/seed/seed-orgs.mjs) automates steps 2 and 3 for the local Keycloak with the Organizations API, and you can adapt it to your realm. The role that grants access to an app is `appRole` in `apps/*/src/app/auth.tsx`. diff --git a/multitenant/apps/aquarium/.env b/multitenant/apps/aquarium/.env new file mode 100644 index 0000000..c43fbe9 --- /dev/null +++ b/multitenant/apps/aquarium/.env @@ -0,0 +1,4 @@ +VITE_OIDC_ISSUER_URI=http://localhost:8080/auth/realms/p2examples +VITE_OIDC_CLIENT_ID=aquarium +VITE_OIDC_USE_MOCK=false +VITE_OIDC_SPA_DEBUG=false diff --git a/multitenant/apps/aquarium/.env.local.sample b/multitenant/apps/aquarium/.env.local.sample new file mode 100644 index 0000000..45e667c --- /dev/null +++ b/multitenant/apps/aquarium/.env.local.sample @@ -0,0 +1,2 @@ +VITE_OIDC_ISSUER_URI=https://your-keycloak.example.com/auth/realms/your-realm +VITE_OIDC_CLIENT_ID=aquarium diff --git a/multitenant/apps/aquarium/eslint.config.js b/multitenant/apps/aquarium/eslint.config.js deleted file mode 100644 index 2f6e3f0..0000000 --- a/multitenant/apps/aquarium/eslint.config.js +++ /dev/null @@ -1,12 +0,0 @@ -const nx = require('@nx/eslint-plugin'); -const baseConfig = require('../../eslint.config.js'); - -module.exports = [ - ...baseConfig, - ...nx.configs['flat/react'], - { - files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], - // Override or add rules here - rules: {}, - }, -]; diff --git a/multitenant/apps/aquarium/eslint.config.mjs b/multitenant/apps/aquarium/eslint.config.mjs new file mode 100644 index 0000000..2a7f6f1 --- /dev/null +++ b/multitenant/apps/aquarium/eslint.config.mjs @@ -0,0 +1,4 @@ +import nx from '@nx/eslint-plugin'; +import baseConfig from '../../eslint.config.mjs'; + +export default [...baseConfig, ...nx.configs['flat/react']]; diff --git a/multitenant/apps/aquarium/index.html b/multitenant/apps/aquarium/index.html index c4996f0..e0078d2 100644 --- a/multitenant/apps/aquarium/index.html +++ b/multitenant/apps/aquarium/index.html @@ -1,13 +1,14 @@ - + - - Aquarium - - - - - + + + + + Phase Two Β· Multitenant Β· Aquarium
diff --git a/multitenant/apps/aquarium/postcss.config.js b/multitenant/apps/aquarium/postcss.config.js deleted file mode 100644 index c72626d..0000000 --- a/multitenant/apps/aquarium/postcss.config.js +++ /dev/null @@ -1,15 +0,0 @@ -const { join } = require('path'); - -// Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build -// option from your application's configuration (i.e. project.json). -// -// See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries - -module.exports = { - plugins: { - tailwindcss: { - config: join(__dirname, 'tailwind.config.js'), - }, - autoprefixer: {}, - }, -}; diff --git a/multitenant/apps/aquarium/project.json b/multitenant/apps/aquarium/project.json index 2f99dfd..aaab4d9 100644 --- a/multitenant/apps/aquarium/project.json +++ b/multitenant/apps/aquarium/project.json @@ -3,7 +3,5 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "apps/aquarium/src", "projectType": "application", - "tags": [], - "// targets": "to see all targets run: nx show project aquarium --web", - "targets": {} + "tags": [] } diff --git a/multitenant/apps/aquarium/public/silent-sso.htm b/multitenant/apps/aquarium/public/silent-sso.htm deleted file mode 100644 index 68259a6..0000000 --- a/multitenant/apps/aquarium/public/silent-sso.htm +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/multitenant/apps/aquarium/src/app/api.tsx b/multitenant/apps/aquarium/src/app/api.tsx deleted file mode 100644 index a619289..0000000 --- a/multitenant/apps/aquarium/src/app/api.tsx +++ /dev/null @@ -1,44 +0,0 @@ -// src/api/ApiContext.tsx -import React, { createContext, useContext, useEffect, useState } from 'react'; -import { ApiManager } from '@multitenant/api-manager'; -import { getOidc } from '../main'; - -// Create the context -const ApiContext = createContext(null); - -// Create a provider component -export const ApiProvider: React.FC<{ children: React.ReactNode }> = ({ - children, -}) => { - const [apiManager, setApiManager] = useState(null); - const [isLoading, setIsLoading] = useState(true); - - useEffect(() => { - const initializeApiManager = async () => { - const oidc = await getOidc(); - const manager = new ApiManager(); - await manager.initialize({ oidc: oidc }); // Initialize the API manager asynchronously - setApiManager(manager); - setIsLoading(false); - }; - - initializeApiManager(); - }, []); - - if (isLoading) { - return
Loading...
; - } - - return ( - {children} - ); -}; - -// Custom hook to use the API manager in components -export const useApiManager = () => { - const context = useContext(ApiContext); - if (!context) { - throw new Error('useApiManager must be used within an ApiProvider'); - } - return context; -}; diff --git a/multitenant/apps/aquarium/src/app/app.spec.tsx b/multitenant/apps/aquarium/src/app/app.spec.tsx index e7122d7..4461dc6 100644 --- a/multitenant/apps/aquarium/src/app/app.spec.tsx +++ b/multitenant/apps/aquarium/src/app/app.spec.tsx @@ -1,15 +1,13 @@ -import { render } from '@testing-library/react'; - -import App from './app'; +import { render, screen } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { App } from './app'; describe('App', () => { - it('should render successfully', () => { - const { baseElement } = render(); - expect(baseElement).toBeTruthy(); - }); + it('shows the logged out state', async () => { + render(); - it('should have a greeting as the title', () => { - const { getByText } = render(); - expect(getByText(/Welcome zoo/gi)).toBeTruthy(); + expect(await screen.findByText('Not authenticated.')).toBeTruthy(); + expect(screen.getByRole('button', { name: 'Log in' })).toBeTruthy(); + expect(screen.getByRole('heading', { name: 'Aquarium' })).toBeTruthy(); }); }); diff --git a/multitenant/apps/aquarium/src/app/app.tsx b/multitenant/apps/aquarium/src/app/app.tsx index cd4a802..dfb7db4 100644 --- a/multitenant/apps/aquarium/src/app/app.tsx +++ b/multitenant/apps/aquarium/src/app/app.tsx @@ -1,12 +1,20 @@ -import Auth from './auth'; import { AppLayout } from '@multitenant/ui-shared'; +import { OidcInitializationGate } from '../oidc'; +import { Auth } from './auth'; -const appName = 'aquarium'; -// hard define it or pull from url or something -const tenant = 'local'; - -function App() { - return ; +export function App() { + return ( + +
Your current status is:
+ + Loading authentication… + + } + > + + +
+ ); } - -export default App; diff --git a/multitenant/apps/aquarium/src/app/auth.tsx b/multitenant/apps/aquarium/src/app/auth.tsx index 7c69128..8c66e3f 100644 --- a/multitenant/apps/aquarium/src/app/auth.tsx +++ b/multitenant/apps/aquarium/src/app/auth.tsx @@ -1,71 +1,38 @@ -import { useEffect, useState } from 'react'; -import { MyOrganizationRepresentation } from '@multitenant/phasetwo-orgs-api'; -import { useOidc } from '../main'; -import { Organizations } from '@multitenant/ui-shared'; -import { useApiManager } from './api'; - -type Applications = { - [key: string]: MyOrganizationRepresentation; -}; - -const Auth = () => { - const { isUserLoggedIn, login, logout, oidcTokens } = useOidc(); - - let content; - - const apiManager = useApiManager(); // Access the API manager - const [applications, setApplications] = useState(null); - - useEffect(() => { - const fetchMe = async () => { - try { - const organizations = await apiManager.fetchP2OrganizationsOrgsGetMe(); - setApplications(organizations); - } catch (error) { - console.error('Error fetching client details:', error); - } - }; - - fetchMe(); - }, [apiManager]); - - if (isUserLoggedIn) { - content = ( -
-
Authenticated
-
-
{oidcTokens.decodedIdToken?.email as string}
-
{oidcTokens.decodedIdToken?.sub as string}
+import { Button, Organizations } from '@multitenant/ui-shared'; +import { useOidc } from '../oidc'; +import { orgsApi } from '../orgs-api'; + +const appRole = 'aquarium'; + +export function Auth() { + const oidc = useOidc(); + + if (oidc.isUserLoggedIn) { + const { decodedIdToken } = oidc; + return ( + <> +
Authenticated
+
+
{decodedIdToken.name ?? decodedIdToken.preferred_username}
+
{decodedIdToken.email}
- - -
- ); - } else { - content = ( -
-
Not authenticated.
- -
+ + + ); } return ( -
-
Your current status is:
- {content} -
+ <> +
Not authenticated.
+ {oidc.initializationError && ( +
+ {oidc.initializationError.message} +
+ )} + + ); -}; - -export default Auth; +} diff --git a/multitenant/apps/aquarium/src/assets/.gitkeep b/multitenant/apps/aquarium/src/assets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/multitenant/apps/aquarium/src/env.d.ts b/multitenant/apps/aquarium/src/env.d.ts new file mode 100644 index 0000000..4152a62 --- /dev/null +++ b/multitenant/apps/aquarium/src/env.d.ts @@ -0,0 +1,10 @@ +interface ImportMetaEnv { + readonly VITE_OIDC_ISSUER_URI: string; + readonly VITE_OIDC_CLIENT_ID: string; + readonly VITE_OIDC_USE_MOCK?: string; + readonly VITE_OIDC_SPA_DEBUG?: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/multitenant/apps/aquarium/src/main.tsx b/multitenant/apps/aquarium/src/main.tsx index 20ea1f3..0f6bd83 100644 --- a/multitenant/apps/aquarium/src/main.tsx +++ b/multitenant/apps/aquarium/src/main.tsx @@ -1,34 +1,10 @@ import { StrictMode } from 'react'; -import * as ReactDOM from 'react-dom/client'; -import App from './app/app'; -import { createReactOidc } from 'oidc-spa/react'; -import { ApiProvider } from './app/api'; -import { REALM } from '@multitenant/api-manager'; +import { createRoot } from 'react-dom/client'; +import { App } from './app/app'; +import './styles.css'; -const realm = ''; -const client = ''; - -export const { OidcProvider, useOidc, getOidc } = createReactOidc({ - // NOTE: If you don't have the params right away see note below. - issuerUri: `https://app.phasetwo.io/auth/realms/${REALM}`, - clientId: client, - /** - * Vite: `publicUrl: import.meta.env.BASE_URL` - * CRA: `publicUrl: process.env.PUBLIC_URL` - * Other: `publicUrl: "/"` (Usually) - */ - publicUrl: '/', -}); - -const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement -); -root.render( +createRoot(document.getElementById('root') as HTMLElement).render( - Checking authentication βŒ›οΈ}> - - - - - + + , ); diff --git a/multitenant/apps/aquarium/src/oidc.ts b/multitenant/apps/aquarium/src/oidc.ts new file mode 100644 index 0000000..d60c4ba --- /dev/null +++ b/multitenant/apps/aquarium/src/oidc.ts @@ -0,0 +1,32 @@ +import { oidcSpa } from 'oidc-spa/react-spa'; +import { z } from 'zod'; + +export const { bootstrapOidc, useOidc, getOidc, OidcInitializationGate } = + oidcSpa + .withExpectedDecodedIdTokenShape({ + decodedIdTokenSchema: z.looseObject({ + sub: z.string(), + name: z.string().optional(), + email: z.string().optional(), + preferred_username: z.string().optional(), + }), + decodedIdToken_mock: { + sub: 'mock-user', + name: 'Mock User', + email: 'mock.user@example.com', + preferred_username: 'mock-user', + }, + }) + .createUtils(); + +bootstrapOidc( + import.meta.env.VITE_OIDC_USE_MOCK === 'true' + ? { implementation: 'mock', isUserInitiallyLoggedIn: false } + : { + implementation: 'real', + issuerUri: import.meta.env.VITE_OIDC_ISSUER_URI, + clientId: import.meta.env.VITE_OIDC_CLIENT_ID, + scopes: ['profile', 'email'], + debugLogs: import.meta.env.VITE_OIDC_SPA_DEBUG === 'true', + }, +); diff --git a/multitenant/apps/aquarium/src/orgs-api.ts b/multitenant/apps/aquarium/src/orgs-api.ts new file mode 100644 index 0000000..9475503 --- /dev/null +++ b/multitenant/apps/aquarium/src/orgs-api.ts @@ -0,0 +1,8 @@ +import { createOrgsApi } from '@multitenant/api-manager'; +import { getOidc } from './oidc'; + +export const orgsApi = createOrgsApi({ + issuerUri: import.meta.env.VITE_OIDC_ISSUER_URI, + getAccessToken: async () => + (await getOidc({ assert: 'user logged in' })).getAccessToken(), +}); diff --git a/multitenant/apps/aquarium/src/styles.css b/multitenant/apps/aquarium/src/styles.css index 844323d..58afd46 100644 --- a/multitenant/apps/aquarium/src/styles.css +++ b/multitenant/apps/aquarium/src/styles.css @@ -1,4 +1,44 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; -/* You can add global styles to this file, and also import other style files */ +@import 'tailwindcss'; +@source '../../../libs/ui-shared/src'; + +@theme { + --color-p2blue-100: #f9fcfe; + --color-p2blue-200: #edf5fb; + --color-p2blue-500: #5b9fdd; + --color-p2blue-700: #1570c2; + --color-p2blue-900: #3c474e; + --color-p2gray-800: #1c1d1e; + --color-p2gray-900: #252627; + --color-p2grad-100: #739fe5; + --color-p2grad-200: #295398; + --color-p2dark-900: #111111; + --color-p2dark-1000: #000000; + --drop-shadow-btn-dark: 0px 1px 8px rgba(11, 25, 35, 0.4); + --drop-shadow-btn-light: 0px 1px 8px rgba(11, 25, 35, 0.1); +} + +@layer components { + .page-bg { + background-position: top center; + background-repeat: no-repeat; + background-size: 100% auto; + } + + .page-home { + position: absolute; + top: 0; + left: 0; + z-index: -1; + width: 100vw; + height: 100vh; + } + + @media (min-width: 768px) { + .page-home { + left: 50%; + transform: translateX(-50%); + object-fit: cover; + object-position: bottom; + } + } +} diff --git a/multitenant/apps/aquarium/tailwind.config.js b/multitenant/apps/aquarium/tailwind.config.js deleted file mode 100644 index e1cf7ce..0000000 --- a/multitenant/apps/aquarium/tailwind.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); -const { join } = require('path'); - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: [ - join( - __dirname, - '{src,pages,components,app}/**/*!(*.stories|*.spec).{ts,tsx,html}' - ), - ...createGlobPatternsForDependencies(__dirname), - ], - theme: { - extend: {}, - }, - plugins: [], -}; diff --git a/multitenant/apps/aquarium/tsconfig.app.json b/multitenant/apps/aquarium/tsconfig.app.json deleted file mode 100644 index 6d35def..0000000 --- a/multitenant/apps/aquarium/tsconfig.app.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": [ - "node", - "@nx/react/typings/cssmodule.d.ts", - "@nx/react/typings/image.d.ts", - "vite/client" - ] - }, - "exclude": [ - "src/**/*.spec.ts", - "src/**/*.test.ts", - "src/**/*.spec.tsx", - "src/**/*.test.tsx", - "src/**/*.spec.js", - "src/**/*.test.js", - "src/**/*.spec.jsx", - "src/**/*.test.jsx", - "vite.config.ts", - "vite.config.mts", - "vitest.config.ts", - "vitest.config.mts" - ], - "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"] -} diff --git a/multitenant/apps/aquarium/tsconfig.json b/multitenant/apps/aquarium/tsconfig.json index fdfab6c..88441e5 100644 --- a/multitenant/apps/aquarium/tsconfig.json +++ b/multitenant/apps/aquarium/tsconfig.json @@ -1,21 +1,7 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "jsx": "react-jsx", - "allowJs": false, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "strict": true, - "types": ["vite/client", "vitest"] + "types": ["node", "vite/client"] }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "extends": "../../tsconfig.base.json" + "include": ["src", "vite.config.ts"] } diff --git a/multitenant/apps/aquarium/tsconfig.spec.json b/multitenant/apps/aquarium/tsconfig.spec.json deleted file mode 100644 index 9d3bb72..0000000 --- a/multitenant/apps/aquarium/tsconfig.spec.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": [ - "vitest/globals", - "vitest/importMeta", - "vite/client", - "node", - "vitest", - "@nx/react/typings/cssmodule.d.ts", - "@nx/react/typings/image.d.ts" - ] - }, - "include": [ - "vite.config.ts", - "vite.config.mts", - "vitest.config.ts", - "vitest.config.mts", - "src/**/*.test.ts", - "src/**/*.spec.ts", - "src/**/*.test.tsx", - "src/**/*.spec.tsx", - "src/**/*.test.js", - "src/**/*.spec.js", - "src/**/*.test.jsx", - "src/**/*.spec.jsx", - "src/**/*.d.ts" - ] -} diff --git a/multitenant/apps/aquarium/vite.config.ts b/multitenant/apps/aquarium/vite.config.ts index 5a470cb..085ed37 100644 --- a/multitenant/apps/aquarium/vite.config.ts +++ b/multitenant/apps/aquarium/vite.config.ts @@ -1,42 +1,29 @@ -/// -import { defineConfig } from 'vite'; +import tailwindcss from '@tailwindcss/vite'; import react from '@vitejs/plugin-react'; -import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; -import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin'; +import { oidcSpa } from 'oidc-spa/vite-plugin'; +import { defineConfig } from 'vitest/config'; export default defineConfig({ - root: __dirname, + root: import.meta.dirname, cacheDir: '../../node_modules/.vite/apps/aquarium', - server: { - port: 4200, - host: 'localhost', - }, - preview: { - port: 4300, - host: 'localhost', - }, - plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])], - // Uncomment this if you are using workers. - // worker: { - // plugins: [ nxViteTsPaths() ], - // }, + plugins: [ + react(), + tailwindcss(), + oidcSpa({ browserRuntimeFreeze: { enabled: true } }), + ], + resolve: { tsconfigPaths: true }, + server: { port: 4201, strictPort: true }, + preview: { port: 4201, strictPort: true }, build: { outDir: '../../dist/apps/aquarium', emptyOutDir: true, - reportCompressedSize: true, - commonjsOptions: { - transformMixedEsModules: true, - }, }, test: { + name: 'aquarium', watch: false, globals: true, environment: 'jsdom', - include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], - reporters: ['default'], - coverage: { - reportsDirectory: '../../coverage/apps/aquarium', - provider: 'v8', - }, + include: ['src/**/*.spec.{ts,tsx}'], + env: { VITE_OIDC_USE_MOCK: 'true' }, }, }); diff --git a/multitenant/apps/zoo/.env b/multitenant/apps/zoo/.env new file mode 100644 index 0000000..78b169f --- /dev/null +++ b/multitenant/apps/zoo/.env @@ -0,0 +1,4 @@ +VITE_OIDC_ISSUER_URI=http://localhost:8080/auth/realms/p2examples +VITE_OIDC_CLIENT_ID=zoo +VITE_OIDC_USE_MOCK=false +VITE_OIDC_SPA_DEBUG=false diff --git a/multitenant/apps/zoo/.env.local.sample b/multitenant/apps/zoo/.env.local.sample new file mode 100644 index 0000000..42753f6 --- /dev/null +++ b/multitenant/apps/zoo/.env.local.sample @@ -0,0 +1,2 @@ +VITE_OIDC_ISSUER_URI=https://your-keycloak.example.com/auth/realms/your-realm +VITE_OIDC_CLIENT_ID=zoo diff --git a/multitenant/apps/zoo/eslint.config.js b/multitenant/apps/zoo/eslint.config.js deleted file mode 100644 index 2f6e3f0..0000000 --- a/multitenant/apps/zoo/eslint.config.js +++ /dev/null @@ -1,12 +0,0 @@ -const nx = require('@nx/eslint-plugin'); -const baseConfig = require('../../eslint.config.js'); - -module.exports = [ - ...baseConfig, - ...nx.configs['flat/react'], - { - files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], - // Override or add rules here - rules: {}, - }, -]; diff --git a/multitenant/apps/zoo/eslint.config.mjs b/multitenant/apps/zoo/eslint.config.mjs new file mode 100644 index 0000000..2a7f6f1 --- /dev/null +++ b/multitenant/apps/zoo/eslint.config.mjs @@ -0,0 +1,4 @@ +import nx from '@nx/eslint-plugin'; +import baseConfig from '../../eslint.config.mjs'; + +export default [...baseConfig, ...nx.configs['flat/react']]; diff --git a/multitenant/apps/zoo/index.html b/multitenant/apps/zoo/index.html index 9c026a7..0c94381 100644 --- a/multitenant/apps/zoo/index.html +++ b/multitenant/apps/zoo/index.html @@ -1,13 +1,14 @@ - + - - Zoo - - - - - + + + + + Phase Two Β· Multitenant Β· Zoo
diff --git a/multitenant/apps/zoo/jest.config.ts b/multitenant/apps/zoo/jest.config.ts deleted file mode 100644 index 0cab6d1..0000000 --- a/multitenant/apps/zoo/jest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -export default { - displayName: 'zoo', - preset: '../../jest.preset.js', - transform: { - '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '@nx/react/plugins/jest', - '^.+\\.[tj]sx?$': ['babel-jest', { presets: ['@nx/react/babel'] }], - }, - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], - coverageDirectory: '../../coverage/apps/zoo', -}; diff --git a/multitenant/apps/zoo/postcss.config.js b/multitenant/apps/zoo/postcss.config.js deleted file mode 100644 index c72626d..0000000 --- a/multitenant/apps/zoo/postcss.config.js +++ /dev/null @@ -1,15 +0,0 @@ -const { join } = require('path'); - -// Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build -// option from your application's configuration (i.e. project.json). -// -// See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries - -module.exports = { - plugins: { - tailwindcss: { - config: join(__dirname, 'tailwind.config.js'), - }, - autoprefixer: {}, - }, -}; diff --git a/multitenant/apps/zoo/project.json b/multitenant/apps/zoo/project.json index a28c8cb..8df2c73 100644 --- a/multitenant/apps/zoo/project.json +++ b/multitenant/apps/zoo/project.json @@ -3,7 +3,5 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "apps/zoo/src", "projectType": "application", - "tags": [], - "// targets": "to see all targets run: nx show project zoo --web", - "targets": {} + "tags": [] } diff --git a/multitenant/apps/zoo/public/silent-sso.htm b/multitenant/apps/zoo/public/silent-sso.htm deleted file mode 100644 index 68259a6..0000000 --- a/multitenant/apps/zoo/public/silent-sso.htm +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - diff --git a/multitenant/apps/zoo/src/app/api.tsx b/multitenant/apps/zoo/src/app/api.tsx deleted file mode 100644 index a619289..0000000 --- a/multitenant/apps/zoo/src/app/api.tsx +++ /dev/null @@ -1,44 +0,0 @@ -// src/api/ApiContext.tsx -import React, { createContext, useContext, useEffect, useState } from 'react'; -import { ApiManager } from '@multitenant/api-manager'; -import { getOidc } from '../main'; - -// Create the context -const ApiContext = createContext(null); - -// Create a provider component -export const ApiProvider: React.FC<{ children: React.ReactNode }> = ({ - children, -}) => { - const [apiManager, setApiManager] = useState(null); - const [isLoading, setIsLoading] = useState(true); - - useEffect(() => { - const initializeApiManager = async () => { - const oidc = await getOidc(); - const manager = new ApiManager(); - await manager.initialize({ oidc: oidc }); // Initialize the API manager asynchronously - setApiManager(manager); - setIsLoading(false); - }; - - initializeApiManager(); - }, []); - - if (isLoading) { - return
Loading...
; - } - - return ( - {children} - ); -}; - -// Custom hook to use the API manager in components -export const useApiManager = () => { - const context = useContext(ApiContext); - if (!context) { - throw new Error('useApiManager must be used within an ApiProvider'); - } - return context; -}; diff --git a/multitenant/apps/zoo/src/app/app.spec.tsx b/multitenant/apps/zoo/src/app/app.spec.tsx index e7122d7..1a2e2f8 100644 --- a/multitenant/apps/zoo/src/app/app.spec.tsx +++ b/multitenant/apps/zoo/src/app/app.spec.tsx @@ -1,15 +1,13 @@ -import { render } from '@testing-library/react'; - -import App from './app'; +import { render, screen } from '@testing-library/react'; +import { describe, expect, it } from 'vitest'; +import { App } from './app'; describe('App', () => { - it('should render successfully', () => { - const { baseElement } = render(); - expect(baseElement).toBeTruthy(); - }); + it('shows the logged out state', async () => { + render(); - it('should have a greeting as the title', () => { - const { getByText } = render(); - expect(getByText(/Welcome zoo/gi)).toBeTruthy(); + expect(await screen.findByText('Not authenticated.')).toBeTruthy(); + expect(screen.getByRole('button', { name: 'Log in' })).toBeTruthy(); + expect(screen.getByRole('heading', { name: 'Zoo' })).toBeTruthy(); }); }); diff --git a/multitenant/apps/zoo/src/app/app.tsx b/multitenant/apps/zoo/src/app/app.tsx index fa40f7a..afc1c1d 100644 --- a/multitenant/apps/zoo/src/app/app.tsx +++ b/multitenant/apps/zoo/src/app/app.tsx @@ -1,12 +1,20 @@ -import Auth from './auth'; import { AppLayout } from '@multitenant/ui-shared'; +import { OidcInitializationGate } from '../oidc'; +import { Auth } from './auth'; -const appName = 'zoo'; -// hard define it or pull from url or something -const tenant = 'local'; - -function App() { - return ; +export function App() { + return ( + +
Your current status is:
+ + Loading authentication… +
+ } + > + + +
+ ); } - -export default App; diff --git a/multitenant/apps/zoo/src/app/auth.tsx b/multitenant/apps/zoo/src/app/auth.tsx index 7c69128..b95feef 100644 --- a/multitenant/apps/zoo/src/app/auth.tsx +++ b/multitenant/apps/zoo/src/app/auth.tsx @@ -1,71 +1,38 @@ -import { useEffect, useState } from 'react'; -import { MyOrganizationRepresentation } from '@multitenant/phasetwo-orgs-api'; -import { useOidc } from '../main'; -import { Organizations } from '@multitenant/ui-shared'; -import { useApiManager } from './api'; - -type Applications = { - [key: string]: MyOrganizationRepresentation; -}; - -const Auth = () => { - const { isUserLoggedIn, login, logout, oidcTokens } = useOidc(); - - let content; - - const apiManager = useApiManager(); // Access the API manager - const [applications, setApplications] = useState(null); - - useEffect(() => { - const fetchMe = async () => { - try { - const organizations = await apiManager.fetchP2OrganizationsOrgsGetMe(); - setApplications(organizations); - } catch (error) { - console.error('Error fetching client details:', error); - } - }; - - fetchMe(); - }, [apiManager]); - - if (isUserLoggedIn) { - content = ( -
-
Authenticated
-
-
{oidcTokens.decodedIdToken?.email as string}
-
{oidcTokens.decodedIdToken?.sub as string}
+import { Button, Organizations } from '@multitenant/ui-shared'; +import { useOidc } from '../oidc'; +import { orgsApi } from '../orgs-api'; + +const appRole = 'zoo'; + +export function Auth() { + const oidc = useOidc(); + + if (oidc.isUserLoggedIn) { + const { decodedIdToken } = oidc; + return ( + <> +
Authenticated
+
+
{decodedIdToken.name ?? decodedIdToken.preferred_username}
+
{decodedIdToken.email}
- - -
- ); - } else { - content = ( -
-
Not authenticated.
- -
+ + + ); } return ( -
-
Your current status is:
- {content} -
+ <> +
Not authenticated.
+ {oidc.initializationError && ( +
+ {oidc.initializationError.message} +
+ )} + + ); -}; - -export default Auth; +} diff --git a/multitenant/apps/zoo/src/assets/.gitkeep b/multitenant/apps/zoo/src/assets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/multitenant/apps/zoo/src/env.d.ts b/multitenant/apps/zoo/src/env.d.ts new file mode 100644 index 0000000..4152a62 --- /dev/null +++ b/multitenant/apps/zoo/src/env.d.ts @@ -0,0 +1,10 @@ +interface ImportMetaEnv { + readonly VITE_OIDC_ISSUER_URI: string; + readonly VITE_OIDC_CLIENT_ID: string; + readonly VITE_OIDC_USE_MOCK?: string; + readonly VITE_OIDC_SPA_DEBUG?: string; +} + +interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/multitenant/apps/zoo/src/main.tsx b/multitenant/apps/zoo/src/main.tsx index d0933a4..0f6bd83 100644 --- a/multitenant/apps/zoo/src/main.tsx +++ b/multitenant/apps/zoo/src/main.tsx @@ -1,33 +1,10 @@ import { StrictMode } from 'react'; -import * as ReactDOM from 'react-dom/client'; -import App from './app/app'; -import { createReactOidc } from 'oidc-spa/react'; -import { ApiProvider } from './app/api'; -import { REALM } from '@multitenant/api-manager'; +import { createRoot } from 'react-dom/client'; +import { App } from './app/app'; +import './styles.css'; -const client = ''; - -export const { OidcProvider, useOidc, getOidc } = createReactOidc({ - // NOTE: If you don't have the params right away see note below. - issuerUri: `https://app.phasetwo.io/auth/realms/${REALM}`, - clientId: client, - /** - * Vite: `publicUrl: import.meta.env.BASE_URL` - * CRA: `publicUrl: process.env.PUBLIC_URL` - * Other: `publicUrl: "/"` (Usually) - */ - publicUrl: '/', -}); - -const root = ReactDOM.createRoot( - document.getElementById('root') as HTMLElement -); -root.render( +createRoot(document.getElementById('root') as HTMLElement).render( - Checking authentication βŒ›οΈ}> - - - - - + + , ); diff --git a/multitenant/apps/zoo/src/oidc.ts b/multitenant/apps/zoo/src/oidc.ts new file mode 100644 index 0000000..d60c4ba --- /dev/null +++ b/multitenant/apps/zoo/src/oidc.ts @@ -0,0 +1,32 @@ +import { oidcSpa } from 'oidc-spa/react-spa'; +import { z } from 'zod'; + +export const { bootstrapOidc, useOidc, getOidc, OidcInitializationGate } = + oidcSpa + .withExpectedDecodedIdTokenShape({ + decodedIdTokenSchema: z.looseObject({ + sub: z.string(), + name: z.string().optional(), + email: z.string().optional(), + preferred_username: z.string().optional(), + }), + decodedIdToken_mock: { + sub: 'mock-user', + name: 'Mock User', + email: 'mock.user@example.com', + preferred_username: 'mock-user', + }, + }) + .createUtils(); + +bootstrapOidc( + import.meta.env.VITE_OIDC_USE_MOCK === 'true' + ? { implementation: 'mock', isUserInitiallyLoggedIn: false } + : { + implementation: 'real', + issuerUri: import.meta.env.VITE_OIDC_ISSUER_URI, + clientId: import.meta.env.VITE_OIDC_CLIENT_ID, + scopes: ['profile', 'email'], + debugLogs: import.meta.env.VITE_OIDC_SPA_DEBUG === 'true', + }, +); diff --git a/multitenant/apps/zoo/src/orgs-api.ts b/multitenant/apps/zoo/src/orgs-api.ts new file mode 100644 index 0000000..9475503 --- /dev/null +++ b/multitenant/apps/zoo/src/orgs-api.ts @@ -0,0 +1,8 @@ +import { createOrgsApi } from '@multitenant/api-manager'; +import { getOidc } from './oidc'; + +export const orgsApi = createOrgsApi({ + issuerUri: import.meta.env.VITE_OIDC_ISSUER_URI, + getAccessToken: async () => + (await getOidc({ assert: 'user logged in' })).getAccessToken(), +}); diff --git a/multitenant/apps/zoo/src/styles.css b/multitenant/apps/zoo/src/styles.css index 844323d..58afd46 100644 --- a/multitenant/apps/zoo/src/styles.css +++ b/multitenant/apps/zoo/src/styles.css @@ -1,4 +1,44 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; -/* You can add global styles to this file, and also import other style files */ +@import 'tailwindcss'; +@source '../../../libs/ui-shared/src'; + +@theme { + --color-p2blue-100: #f9fcfe; + --color-p2blue-200: #edf5fb; + --color-p2blue-500: #5b9fdd; + --color-p2blue-700: #1570c2; + --color-p2blue-900: #3c474e; + --color-p2gray-800: #1c1d1e; + --color-p2gray-900: #252627; + --color-p2grad-100: #739fe5; + --color-p2grad-200: #295398; + --color-p2dark-900: #111111; + --color-p2dark-1000: #000000; + --drop-shadow-btn-dark: 0px 1px 8px rgba(11, 25, 35, 0.4); + --drop-shadow-btn-light: 0px 1px 8px rgba(11, 25, 35, 0.1); +} + +@layer components { + .page-bg { + background-position: top center; + background-repeat: no-repeat; + background-size: 100% auto; + } + + .page-home { + position: absolute; + top: 0; + left: 0; + z-index: -1; + width: 100vw; + height: 100vh; + } + + @media (min-width: 768px) { + .page-home { + left: 50%; + transform: translateX(-50%); + object-fit: cover; + object-position: bottom; + } + } +} diff --git a/multitenant/apps/zoo/tailwind.config.js b/multitenant/apps/zoo/tailwind.config.js deleted file mode 100644 index e1cf7ce..0000000 --- a/multitenant/apps/zoo/tailwind.config.js +++ /dev/null @@ -1,17 +0,0 @@ -const { createGlobPatternsForDependencies } = require('@nx/react/tailwind'); -const { join } = require('path'); - -/** @type {import('tailwindcss').Config} */ -module.exports = { - content: [ - join( - __dirname, - '{src,pages,components,app}/**/*!(*.stories|*.spec).{ts,tsx,html}' - ), - ...createGlobPatternsForDependencies(__dirname), - ], - theme: { - extend: {}, - }, - plugins: [], -}; diff --git a/multitenant/apps/zoo/tsconfig.app.json b/multitenant/apps/zoo/tsconfig.app.json deleted file mode 100644 index db420c0..0000000 --- a/multitenant/apps/zoo/tsconfig.app.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "types": [ - "node", - "@nx/react/typings/cssmodule.d.ts", - "@nx/react/typings/image.d.ts", - "vite/client" - ] - }, - "exclude": [ - "src/**/*.spec.ts", - "src/**/*.test.ts", - "src/**/*.spec.tsx", - "src/**/*.test.tsx", - "src/**/*.spec.js", - "src/**/*.test.js", - "src/**/*.spec.jsx", - "src/**/*.test.jsx", - "jest.config.ts" - ], - "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"] -} diff --git a/multitenant/apps/zoo/tsconfig.json b/multitenant/apps/zoo/tsconfig.json index b1de769..88441e5 100644 --- a/multitenant/apps/zoo/tsconfig.json +++ b/multitenant/apps/zoo/tsconfig.json @@ -1,21 +1,7 @@ { + "extends": "../../tsconfig.base.json", "compilerOptions": { - "jsx": "react-jsx", - "allowJs": false, - "esModuleInterop": false, - "allowSyntheticDefaultImports": true, - "strict": true, - "types": ["vite/client"] + "types": ["node", "vite/client"] }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.spec.json" - } - ], - "extends": "../../tsconfig.base.json" + "include": ["src", "vite.config.ts"] } diff --git a/multitenant/apps/zoo/tsconfig.spec.json b/multitenant/apps/zoo/tsconfig.spec.json deleted file mode 100644 index 643969a..0000000 --- a/multitenant/apps/zoo/tsconfig.spec.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": [ - "jest", - "node", - "@nx/react/typings/cssmodule.d.ts", - "@nx/react/typings/image.d.ts" - ] - }, - "include": [ - "jest.config.ts", - "src/**/*.test.ts", - "src/**/*.spec.ts", - "src/**/*.test.tsx", - "src/**/*.spec.tsx", - "src/**/*.test.js", - "src/**/*.spec.js", - "src/**/*.test.jsx", - "src/**/*.spec.jsx", - "src/**/*.d.ts" - ] -} diff --git a/multitenant/apps/zoo/vite.config.ts b/multitenant/apps/zoo/vite.config.ts index 1b01159..fca7a8d 100644 --- a/multitenant/apps/zoo/vite.config.ts +++ b/multitenant/apps/zoo/vite.config.ts @@ -1,31 +1,29 @@ -/// -import { defineConfig } from 'vite'; +import tailwindcss from '@tailwindcss/vite'; import react from '@vitejs/plugin-react'; -import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; -import { nxCopyAssetsPlugin } from '@nx/vite/plugins/nx-copy-assets.plugin'; +import { oidcSpa } from 'oidc-spa/vite-plugin'; +import { defineConfig } from 'vitest/config'; export default defineConfig({ - root: __dirname, + root: import.meta.dirname, cacheDir: '../../node_modules/.vite/apps/zoo', - server: { - port: 4200, - host: 'localhost', - }, - preview: { - port: 4300, - host: 'localhost', - }, - plugins: [react(), nxViteTsPaths(), nxCopyAssetsPlugin(['*.md'])], - // Uncomment this if you are using workers. - // worker: { - // plugins: [ nxViteTsPaths() ], - // }, + plugins: [ + react(), + tailwindcss(), + oidcSpa({ browserRuntimeFreeze: { enabled: true } }), + ], + resolve: { tsconfigPaths: true }, + server: { port: 4200, strictPort: true }, + preview: { port: 4200, strictPort: true }, build: { outDir: '../../dist/apps/zoo', emptyOutDir: true, - reportCompressedSize: true, - commonjsOptions: { - transformMixedEsModules: true, - }, + }, + test: { + name: 'zoo', + watch: false, + globals: true, + environment: 'jsdom', + include: ['src/**/*.spec.{ts,tsx}'], + env: { VITE_OIDC_USE_MOCK: 'true' }, }, }); diff --git a/multitenant/eslint.config.js b/multitenant/eslint.config.mjs similarity index 64% rename from multitenant/eslint.config.js rename to multitenant/eslint.config.mjs index 46a8005..a4220f3 100644 --- a/multitenant/eslint.config.js +++ b/multitenant/eslint.config.mjs @@ -1,11 +1,16 @@ -const nx = require('@nx/eslint-plugin'); +import nx from '@nx/eslint-plugin'; -module.exports = [ +export default [ ...nx.configs['flat/base'], ...nx.configs['flat/typescript'], ...nx.configs['flat/javascript'], { - ignores: ['**/dist'], + ignores: [ + '**/dist', + '**/out-tsc', + '**/vite.config.*.timestamp*', + 'libs/phasetwo-orgs-api/src/lib', + ], }, { files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], @@ -14,7 +19,7 @@ module.exports = [ 'error', { enforceBuildableLibDependency: true, - allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?js$'], + allow: ['^.*/eslint(\\.base)?\\.config\\.[cm]?[jt]s$'], depConstraints: [ { sourceTag: '*', @@ -25,9 +30,4 @@ module.exports = [ ], }, }, - { - files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], - // Override or add rules here - rules: {}, - }, ]; diff --git a/multitenant/jest.config.ts b/multitenant/jest.config.ts deleted file mode 100644 index 6b3f2d6..0000000 --- a/multitenant/jest.config.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { getJestProjectsAsync } from '@nx/jest'; - -export default async () => ({ - projects: await getJestProjectsAsync(), -}); diff --git a/multitenant/jest.preset.js b/multitenant/jest.preset.js deleted file mode 100644 index f078ddc..0000000 --- a/multitenant/jest.preset.js +++ /dev/null @@ -1,3 +0,0 @@ -const nxPreset = require('@nx/jest/preset').default; - -module.exports = { ...nxPreset }; diff --git a/multitenant/libs/api-manager/README.md b/multitenant/libs/api-manager/README.md index 7c0c866..992e078 100644 --- a/multitenant/libs/api-manager/README.md +++ b/multitenant/libs/api-manager/README.md @@ -1,11 +1,20 @@ # api-manager -This library was generated with [Nx](https://nx.dev). +`createOrgsApi({ issuerUri, getAccessToken })` wraps the generated [Organizations API client](../phasetwo-orgs-api) for the apps: -## Building +- it derives the Organizations API base URL (`{origin}{relative path}/realms`) and the realm name from the OIDC issuer URI, with `createKeycloakUtils` from `oidc-spa/keycloak`; +- it calls `getAccessToken` before every request, so the apps always send the current access token, which oidc-spa renews in the background. -Run `nx build api-manager` to build the library. +It returns `getMyOrganizations()`, which calls `GET /{realm}/orgs/me` and resolves to the user's organizations, keyed by organization ID, each with its `name`, `displayName` and `roles`. -## Running unit tests +```ts +import { createOrgsApi } from '@multitenant/api-manager'; +import { getOidc } from './oidc'; -Run `nx test api-manager` to execute the unit tests via [Jest](https://jestjs.io). +export const orgsApi = createOrgsApi({ + issuerUri: import.meta.env.VITE_OIDC_ISSUER_URI, + getAccessToken: async () => (await getOidc({ assert: 'user logged in' })).getAccessToken(), +}); +``` + +Run its tests with `pnpm nx test api-manager`. diff --git a/multitenant/libs/api-manager/eslint.config.js b/multitenant/libs/api-manager/eslint.config.js deleted file mode 100644 index 9d2af7a..0000000 --- a/multitenant/libs/api-manager/eslint.config.js +++ /dev/null @@ -1,19 +0,0 @@ -const baseConfig = require('../../eslint.config.js'); - -module.exports = [ - ...baseConfig, - { - files: ['**/*.json'], - rules: { - '@nx/dependency-checks': [ - 'error', - { - ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs}'], - }, - ], - }, - languageOptions: { - parser: require('jsonc-eslint-parser'), - }, - }, -]; diff --git a/multitenant/libs/api-manager/eslint.config.mjs b/multitenant/libs/api-manager/eslint.config.mjs new file mode 100644 index 0000000..b7f6277 --- /dev/null +++ b/multitenant/libs/api-manager/eslint.config.mjs @@ -0,0 +1,3 @@ +import baseConfig from '../../eslint.config.mjs'; + +export default [...baseConfig]; diff --git a/multitenant/libs/api-manager/jest.config.ts b/multitenant/libs/api-manager/jest.config.ts deleted file mode 100644 index d179354..0000000 --- a/multitenant/libs/api-manager/jest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -export default { - displayName: 'api-manager', - preset: '../../jest.preset.js', - testEnvironment: 'node', - transform: { - '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], - }, - moduleFileExtensions: ['ts', 'js', 'html'], - coverageDirectory: '../../coverage/libs/api-manager', -}; diff --git a/multitenant/libs/api-manager/package-lock.json b/multitenant/libs/api-manager/package-lock.json deleted file mode 100644 index 23e63a2..0000000 --- a/multitenant/libs/api-manager/package-lock.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "@multitenant/api-manager", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@multitenant/api-manager", - "version": "0.0.1", - "dependencies": { - "tslib": "^2.3.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - } - } -} diff --git a/multitenant/libs/api-manager/package.json b/multitenant/libs/api-manager/package.json deleted file mode 100644 index 5873344..0000000 --- a/multitenant/libs/api-manager/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "@multitenant/api-manager", - "version": "0.0.1", - "dependencies": { - "tslib": "^2.3.0" - }, - "type": "commonjs", - "main": "./src/index.js", - "typings": "./src/index.d.ts", - "private": true -} diff --git a/multitenant/libs/api-manager/project.json b/multitenant/libs/api-manager/project.json index 8061b5b..9dee097 100644 --- a/multitenant/libs/api-manager/project.json +++ b/multitenant/libs/api-manager/project.json @@ -3,17 +3,5 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "libs/api-manager/src", "projectType": "library", - "tags": [], - "targets": { - "build": { - "executor": "@nx/js:tsc", - "outputs": ["{options.outputPath}"], - "options": { - "outputPath": "dist/libs/api-manager", - "main": "libs/api-manager/src/index.ts", - "tsConfig": "libs/api-manager/tsconfig.lib.json", - "assets": ["libs/api-manager/*.md"] - } - } - } + "tags": [] } diff --git a/multitenant/libs/api-manager/src/lib/api-manager.spec.ts b/multitenant/libs/api-manager/src/lib/api-manager.spec.ts index 64f3d00..fdeab1a 100644 --- a/multitenant/libs/api-manager/src/lib/api-manager.spec.ts +++ b/multitenant/libs/api-manager/src/lib/api-manager.spec.ts @@ -1,7 +1,53 @@ -import { apiManager } from './api-manager'; +import { afterEach, describe, expect, it, vi } from 'vitest'; +import { createOrgsApi } from './api-manager'; -describe('apiManager', () => { - it('should work', () => { - expect(apiManager()).toEqual('api-manager'); +function stubFetch() { + const fetchMock = vi.fn(async () => + Response.json({ 'org-id': { name: 'california', roles: ['zoo'] } }), + ); + vi.stubGlobal('fetch', fetchMock); + return fetchMock; +} + +describe('createOrgsApi', () => { + afterEach(() => { + vi.unstubAllGlobals(); + }); + + it('calls orgs/me of the realm with a fresh access token each time', async () => { + const fetchMock = stubFetch(); + const tokens = ['first-token', 'second-token']; + const orgsApi = createOrgsApi({ + issuerUri: 'http://localhost:8080/auth/realms/p2examples', + getAccessToken: async () => tokens.shift() ?? '', + }); + + await expect(orgsApi.getMyOrganizations()).resolves.toMatchObject({ + 'org-id': { name: 'california', roles: ['zoo'] }, + }); + await orgsApi.getMyOrganizations(); + + const [[url, firstInit], [, secondInit]] = fetchMock.mock.calls; + expect(url).toBe('http://localhost:8080/auth/realms/p2examples/orgs/me'); + expect(new Headers(firstInit?.headers).get('Authorization')).toBe( + 'Bearer first-token', + ); + expect(new Headers(secondInit?.headers).get('Authorization')).toBe( + 'Bearer second-token', + ); + }); + + it('supports Keycloak without the /auth relative path', async () => { + const fetchMock = stubFetch(); + const orgsApi = createOrgsApi({ + issuerUri: 'https://keycloak.example.com/realms/acme', + getAccessToken: async () => 'token', + }); + + await orgsApi.getMyOrganizations(); + + expect(fetchMock.mock.calls[0]?.[0]).toBe( + 'https://keycloak.example.com/realms/acme/orgs/me', + ); }); }); diff --git a/multitenant/libs/api-manager/src/lib/api-manager.ts b/multitenant/libs/api-manager/src/lib/api-manager.ts index f8ec621..cb66c92 100644 --- a/multitenant/libs/api-manager/src/lib/api-manager.ts +++ b/multitenant/libs/api-manager/src/lib/api-manager.ts @@ -1,62 +1,35 @@ import { - OrganizationsApi, Configuration, + OrganizationsApi, + type MyOrganizationRepresentation, } from '@multitenant/phasetwo-orgs-api'; -import { Oidc } from 'oidc-spa'; - -const BASE_PATH = 'https://app.phasetwo.io/auth'; -export const REALM = ''; - -export class ApiManager { - private isInitialized = false; - // P2 Orgs APIs - private p2OrganizationsApiConfig: Configuration | null = null; - private p2OrganizationsApi: OrganizationsApi | null = null; - - public async initialize({ oidc }: { oidc: Oidc> }) { - if (!this.isInitialized) { - try { - await this.initializeConfigAndApis({ oidc }); - this.isInitialized = true; - } catch (error) { - console.error('Error initializing API manager:', error); - } - } - } - - private async initializeConfigAndApis({ - oidc, - }: { - oidc: Oidc>; - }) { - if (!oidc.isUserLoggedIn) { - throw new Error('User is not logged in.'); - } - - const accessToken = await oidc.getTokens().accessToken; - - // P2 Orgs APIs - this.p2OrganizationsApiConfig = new Configuration({ - basePath: `${BASE_PATH}/realms`, - headers: { - Authorization: `Bearer ${accessToken}`, - }, - }); - this.p2OrganizationsApi = new OrganizationsApi( - this.p2OrganizationsApiConfig - ); - } - - // P2 Orgs API Methods - public async fetchP2OrganizationsOrgsGetMe() { - if (!this.p2OrganizationsApi) { - throw new Error('OrganizationsApi is not initialized.'); - } - - return this.p2OrganizationsApi.getMe({ - realm: REALM, - }); - } +import { createKeycloakUtils } from 'oidc-spa/keycloak'; + +export type MyOrganizations = Record; + +export type OrgsApi = { + getMyOrganizations: () => Promise; +}; + +export function createOrgsApi({ + issuerUri, + getAccessToken, +}: { + issuerUri: string; + getAccessToken: () => Promise; +}): OrgsApi { + const { origin, realm, kcHttpRelativePath } = createKeycloakUtils({ + issuerUri, + }).issuerUriParsed; + + const organizationsApi = new OrganizationsApi( + new Configuration({ + basePath: `${origin}${kcHttpRelativePath ?? ''}/realms`, + accessToken: () => getAccessToken(), + }), + ); + + return { + getMyOrganizations: () => organizationsApi.getMe({ realm }), + }; } - -export default ApiManager; diff --git a/multitenant/libs/api-manager/tsconfig.json b/multitenant/libs/api-manager/tsconfig.json index 6f7169a..af44995 100644 --- a/multitenant/libs/api-manager/tsconfig.json +++ b/multitenant/libs/api-manager/tsconfig.json @@ -1,22 +1,7 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "module": "commonjs", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "noPropertyAccessFromIndexSignature": true + "types": ["node"] }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ] + "include": ["src", "vite.config.ts"] } diff --git a/multitenant/libs/api-manager/tsconfig.lib.json b/multitenant/libs/api-manager/tsconfig.lib.json deleted file mode 100644 index 33eca2c..0000000 --- a/multitenant/libs/api-manager/tsconfig.lib.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "declaration": true, - "types": ["node"] - }, - "include": ["src/**/*.ts"], - "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] -} diff --git a/multitenant/libs/api-manager/tsconfig.spec.json b/multitenant/libs/api-manager/tsconfig.spec.json deleted file mode 100644 index 9b2a121..0000000 --- a/multitenant/libs/api-manager/tsconfig.spec.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "include": [ - "jest.config.ts", - "src/**/*.test.ts", - "src/**/*.spec.ts", - "src/**/*.d.ts" - ] -} diff --git a/multitenant/libs/api-manager/vite.config.ts b/multitenant/libs/api-manager/vite.config.ts new file mode 100644 index 0000000..7487c8a --- /dev/null +++ b/multitenant/libs/api-manager/vite.config.ts @@ -0,0 +1,13 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + root: import.meta.dirname, + cacheDir: '../../node_modules/.vite/libs/api-manager', + resolve: { tsconfigPaths: true }, + test: { + name: 'api-manager', + watch: false, + environment: 'node', + include: ['src/**/*.spec.ts'], + }, +}); diff --git a/multitenant/libs/phasetwo-orgs-api/README.md b/multitenant/libs/phasetwo-orgs-api/README.md index b2e46a1..3ba47d2 100644 --- a/multitenant/libs/phasetwo-orgs-api/README.md +++ b/multitenant/libs/phasetwo-orgs-api/README.md @@ -1,11 +1,25 @@ # phasetwo-orgs-api -This library was generated with [Nx](https://nx.dev). +A TypeScript client for the Phase Two Organizations API, generated with [OpenAPI Generator](https://openapi-generator.tech) (`typescript-fetch`) from the [Phase Two OpenAPI spec](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/refs/heads/main/openapi.yaml). The apps only call [`GET /{realm}/orgs/me`](https://phasetwo.io/api/get-me/), through [`api-manager`](../api-manager). -## Building +Everything in `src/lib` is generated. Don't edit it by hand: it is excluded from ESLint and Prettier, and the next regeneration overwrites it. -Run `nx build phasetwo-orgs-api` to build the library. +## Regenerate -## Running unit tests +From the workspace root, with Java 11 or newer on your `PATH`: -Run `nx test phasetwo-orgs-api` to execute the unit tests via [Jest](https://jestjs.io). +```sh +pnpm run generate:orgs-api +``` + +The generator version and options live in [`openapitools.json`](../../openapitools.json): + +| Option | Why | +| ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `globalProperty.apiDocs`, `globalProperty.modelDocs`: `false` | No Markdown docs next to the code. | +| `openapiNormalizer.KEEP_ONLY_FIRST_TAG_IN_OPERATION`: `true` | Some operations have two tags in the spec. Without this they are generated into two API classes, and `apis/index.ts` exports the same request type twice. | +| `globalProperty.skipFormModel`: `false` and `inlineSchemaNameMappings` | Generates the models of the two form request bodies, which the APIs import, under names that don't clash with the generated `*Request` types. | + +The generator doesn't delete files that are no longer part of the spec. If an API or model disappears upstream, delete `src/lib` (except `.openapi-generator-ignore`) before regenerating. + +The generated code doesn't pass `noUnusedLocals`, `noImplicitOverride` or `erasableSyntaxOnly`. The apps import it from source through the `@multitenant/phasetwo-orgs-api` path alias, so it is part of every project's type check, and the workspace [`tsconfig.base.json`](../../tsconfig.base.json) leaves those options off. diff --git a/multitenant/libs/phasetwo-orgs-api/eslint.config.js b/multitenant/libs/phasetwo-orgs-api/eslint.config.js deleted file mode 100644 index 9d2af7a..0000000 --- a/multitenant/libs/phasetwo-orgs-api/eslint.config.js +++ /dev/null @@ -1,19 +0,0 @@ -const baseConfig = require('../../eslint.config.js'); - -module.exports = [ - ...baseConfig, - { - files: ['**/*.json'], - rules: { - '@nx/dependency-checks': [ - 'error', - { - ignoredFiles: ['{projectRoot}/eslint.config.{js,cjs,mjs}'], - }, - ], - }, - languageOptions: { - parser: require('jsonc-eslint-parser'), - }, - }, -]; diff --git a/multitenant/libs/phasetwo-orgs-api/jest.config.ts b/multitenant/libs/phasetwo-orgs-api/jest.config.ts deleted file mode 100644 index 3992849..0000000 --- a/multitenant/libs/phasetwo-orgs-api/jest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -export default { - displayName: 'phasetwo-orgs-api', - preset: '../../jest.preset.js', - testEnvironment: 'node', - transform: { - '^.+\\.[tj]s$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], - }, - moduleFileExtensions: ['ts', 'js', 'html'], - coverageDirectory: '../../coverage/libs/phasetwo-orgs-api', -}; diff --git a/multitenant/libs/phasetwo-orgs-api/package-lock.json b/multitenant/libs/phasetwo-orgs-api/package-lock.json deleted file mode 100644 index e9c9eb2..0000000 --- a/multitenant/libs/phasetwo-orgs-api/package-lock.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "@multitenant/phasetwo-orgs-api", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@multitenant/phasetwo-orgs-api", - "version": "0.0.1", - "dependencies": { - "tslib": "^2.3.0" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - } - } -} diff --git a/multitenant/libs/phasetwo-orgs-api/package.json b/multitenant/libs/phasetwo-orgs-api/package.json deleted file mode 100644 index ed0540a..0000000 --- a/multitenant/libs/phasetwo-orgs-api/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "@multitenant/phasetwo-orgs-api", - "version": "0.0.1", - "dependencies": { - "tslib": "^2.3.0" - }, - "type": "commonjs", - "main": "./src/index.js", - "typings": "./src/index.d.ts", - "private": true -} diff --git a/multitenant/libs/phasetwo-orgs-api/project.json b/multitenant/libs/phasetwo-orgs-api/project.json index 5684eb9..4de2506 100644 --- a/multitenant/libs/phasetwo-orgs-api/project.json +++ b/multitenant/libs/phasetwo-orgs-api/project.json @@ -5,15 +5,13 @@ "projectType": "library", "tags": [], "targets": { - "build": { - "executor": "@nx/js:tsc", - "outputs": ["{options.outputPath}"], + "typecheck": { + "command": "tsc -p tsconfig.json", "options": { - "outputPath": "dist/libs/phasetwo-orgs-api", - "main": "libs/phasetwo-orgs-api/src/index.ts", - "tsConfig": "libs/phasetwo-orgs-api/tsconfig.lib.json", - "assets": ["libs/phasetwo-orgs-api/*.md"] - } + "cwd": "{projectRoot}" + }, + "cache": true, + "inputs": ["production", "^production"] } } } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/.openapi-generator/FILES b/multitenant/libs/phasetwo-orgs-api/src/lib/.openapi-generator/FILES index ebf5366..3cd13c3 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/.openapi-generator/FILES +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/.openapi-generator/FILES @@ -1,29 +1,57 @@ -.openapi-generator-ignore apis/AttributesApi.ts apis/EventsApi.ts apis/IdentityProvidersApi.ts +apis/OrganizationApi.ts apis/OrganizationDomainsApi.ts -apis/OrganizationInvitationsApi.ts +apis/OrganizationInvitationApi.ts apis/OrganizationMembershipsApi.ts apis/OrganizationRolesApi.ts +apis/OrganizationSCIMApi.ts apis/OrganizationsApi.ts apis/UsersApi.ts apis/index.ts index.ts +models/AccessTokenResponse.ts models/AuthDetailsRepresentation.ts +models/BulkResponseItem.ts +models/CreatePortalLinkForm.ts +models/CredentialRepresentation.ts models/EventRepresentation.ts +models/ExternalBasicScimAuth.ts +models/ExternalJwtScimAuth.ts +models/ExternalSecretScimAuth.ts models/IdentityProviderMapperRepresentation.ts models/IdentityProviderRepresentation.ts +models/ImportOrganizationsForm.ts models/InvitationRepresentation.ts models/InvitationRequestRepresentation.ts -models/MagicLinkRepresentation.ts +models/KeycloakScimAuth.ts +models/LinkIdentityProviderRepresentation.ts +models/MagicLinkRequest.ts +models/MagicLinkResponse.ts models/MyOrganizationRepresentation.ts +models/OrganizationConfigRepresentation.ts models/OrganizationDomainRepresentation.ts +models/OrganizationExportRepresentation.ts +models/OrganizationExportRepresentationAllOfMembers.ts +models/OrganizationMemberAttributeRepresentation.ts models/OrganizationRepresentation.ts models/OrganizationRoleRepresentation.ts +models/OrganizationScimAuth.ts +models/OrganizationScimRepresentation.ts +models/OrganizationsConfigRepresentation.ts +models/OrganizationsExportRepresentation.ts +models/OrganizationsImportRepresentation.ts +models/OrganizationsImportResultRepresentation.ts +models/OrganizationsImportResultRepresentationErrorsInner.ts models/PortalLinkRepresentation.ts models/RealmAttributeRepresentation.ts +models/SwitchOrganizationRepresentation.ts +models/UserBriefRepresentation.ts models/UserRepresentation.ts +models/UserWithOrgsBriefRepresentation.ts +models/UserWithOrgsRepresentation.ts models/WebhookRepresentation.ts +models/WebhookSendRepresentation.ts models/index.ts runtime.ts diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/.openapi-generator/VERSION b/multitenant/libs/phasetwo-orgs-api/src/lib/.openapi-generator/VERSION index 4bc5d61..bc34d81 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/.openapi-generator/VERSION +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/.openapi-generator/VERSION @@ -1 +1 @@ -7.9.0 +7.25.0 diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/AttributesApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/AttributesApi.ts index bd4f1ae..194e2b1 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/AttributesApi.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/AttributesApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -12,38 +12,65 @@ * Do not edit the class manually. */ - import * as runtime from '../runtime'; -import type { - RealmAttributeRepresentation, -} from '../models/index'; import { + type RealmAttributeRepresentation, RealmAttributeRepresentationFromJSON, RealmAttributeRepresentationToJSON, -} from '../models/index'; +} from '../models/RealmAttributeRepresentation'; export interface CreateRealmAttributeRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * + */ realmAttributeRepresentation: RealmAttributeRepresentation; } export interface DeleteRealmAttributeRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * attribute key + */ attributeKey: string; } export interface GetRealmAttributeByKeyRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * attribute key + */ attributeKey: string; } export interface GetRealmAttributesRequest { + /** + * realm name (not id!) + */ realm: string; } export interface UpdateRealmAttributeByKeyRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * attribute key + */ attributeKey: string; + /** + * + */ realmAttributeRepresentation: RealmAttributeRepresentation; } @@ -53,9 +80,9 @@ export interface UpdateRealmAttributeByKeyRequest { export class AttributesApi extends runtime.BaseAPI { /** - * Create a new realm attribute + * Creates request options for createRealmAttribute without sending the request */ - async createRealmAttributeRaw(requestParameters: CreateRealmAttributeRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async createRealmAttributeRequestOpts(requestParameters: CreateRealmAttributeRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -84,13 +111,25 @@ export class AttributesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/attributes`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))), + + let urlPath = `/{realm}/attributes`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, method: 'POST', headers: headerParameters, query: queryParameters, body: RealmAttributeRepresentationToJSON(requestParameters['realmAttributeRepresentation']), - }, initOverrides); + }; + } + + /** + * Create a new realm attribute + */ + async createRealmAttributeRaw(requestParameters: CreateRealmAttributeRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.createRealmAttributeRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -103,9 +142,9 @@ export class AttributesApi extends runtime.BaseAPI { } /** - * Delete the realm attribute + * Creates request options for deleteRealmAttribute without sending the request */ - async deleteRealmAttributeRaw(requestParameters: DeleteRealmAttributeRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async deleteRealmAttributeRequestOpts(requestParameters: DeleteRealmAttributeRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -132,12 +171,25 @@ export class AttributesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/attributes/{attributeKey}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"attributeKey"}}`, encodeURIComponent(String(requestParameters['attributeKey']))), + + let urlPath = `/{realm}/attributes/{attributeKey}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{attributeKey}', encodeURIComponent(String(requestParameters['attributeKey']))); + + return { + path: urlPath, method: 'DELETE', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Delete the realm attribute + */ + async deleteRealmAttributeRaw(requestParameters: DeleteRealmAttributeRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.deleteRealmAttributeRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -150,9 +202,9 @@ export class AttributesApi extends runtime.BaseAPI { } /** - * Get realm attribute by key + * Creates request options for getRealmAttributeByKey without sending the request */ - async getRealmAttributeByKeyRaw(requestParameters: GetRealmAttributeByKeyRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async getRealmAttributeByKeyRequestOpts(requestParameters: GetRealmAttributeByKeyRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -179,12 +231,25 @@ export class AttributesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/attributes/{attributeKey}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"attributeKey"}}`, encodeURIComponent(String(requestParameters['attributeKey']))), + + let urlPath = `/{realm}/attributes/{attributeKey}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{attributeKey}', encodeURIComponent(String(requestParameters['attributeKey']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get realm attribute by key + */ + async getRealmAttributeByKeyRaw(requestParameters: GetRealmAttributeByKeyRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getRealmAttributeByKeyRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => RealmAttributeRepresentationFromJSON(jsonValue)); } @@ -198,10 +263,9 @@ export class AttributesApi extends runtime.BaseAPI { } /** - * Get a list of attributes for this realm - * Get realm attributes + * Creates request options for getRealmAttributes without sending the request */ - async getRealmAttributesRaw(requestParameters: GetRealmAttributesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + async getRealmAttributesRequestOpts(requestParameters: GetRealmAttributesRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -221,12 +285,25 @@ export class AttributesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/attributes`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))), + + let urlPath = `/{realm}/attributes`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get a list of attributes for this realm + * Get realm attributes + */ + async getRealmAttributesRaw(requestParameters: GetRealmAttributesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getRealmAttributesRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response); } @@ -241,9 +318,9 @@ export class AttributesApi extends runtime.BaseAPI { } /** - * Update realm attribute by key + * Creates request options for updateRealmAttributeByKey without sending the request */ - async updateRealmAttributeByKeyRaw(requestParameters: UpdateRealmAttributeByKeyRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async updateRealmAttributeByKeyRequestOpts(requestParameters: UpdateRealmAttributeByKeyRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -279,13 +356,26 @@ export class AttributesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/attributes/{attributeKey}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"attributeKey"}}`, encodeURIComponent(String(requestParameters['attributeKey']))), + + let urlPath = `/{realm}/attributes/{attributeKey}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{attributeKey}', encodeURIComponent(String(requestParameters['attributeKey']))); + + return { + path: urlPath, method: 'PUT', headers: headerParameters, query: queryParameters, body: RealmAttributeRepresentationToJSON(requestParameters['realmAttributeRepresentation']), - }, initOverrides); + }; + } + + /** + * Update realm attribute by key + */ + async updateRealmAttributeByKeyRaw(requestParameters: UpdateRealmAttributeByKeyRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.updateRealmAttributeByKeyRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/EventsApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/EventsApi.ts index 5611c17..51d7da3 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/EventsApi.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/EventsApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -12,46 +12,196 @@ * Do not edit the class manually. */ - import * as runtime from '../runtime'; -import type { - EventRepresentation, - WebhookRepresentation, -} from '../models/index'; import { + type CredentialRepresentation, + CredentialRepresentationFromJSON, + CredentialRepresentationToJSON, +} from '../models/CredentialRepresentation'; +import { + type EventRepresentation, EventRepresentationFromJSON, EventRepresentationToJSON, +} from '../models/EventRepresentation'; +import { + type WebhookRepresentation, WebhookRepresentationFromJSON, WebhookRepresentationToJSON, -} from '../models/index'; +} from '../models/WebhookRepresentation'; +import { + type WebhookSendRepresentation, + WebhookSendRepresentationFromJSON, + WebhookSendRepresentationToJSON, +} from '../models/WebhookSendRepresentation'; export interface CreateEventRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * + */ eventRepresentation: EventRepresentation; } export interface CreateWebhookRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * + */ webhookRepresentation: WebhookRepresentation; } export interface DeleteWebhookRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * webhook id + */ webhookId: string; } +export interface GetPayloadByKeycloakTypeAndIdRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * keycloak event type + */ + type: string; + /** + * keycloak event id + */ + kid: string; +} + export interface GetWebhookByIdRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * webhook id + */ + webhookId: string; +} + +export interface GetWebhookSecretByIdRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * webhook id + */ + webhookId: string; +} + +export interface GetWebhookSendByIdRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * webhook id + */ + webhookId: string; + /** + * send id + */ + sendId: string; +} + +export interface GetWebhookSendsRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * webhook id + */ webhookId: string; + /** + * + */ + first?: number; + /** + * + */ + max?: number; +} + +export interface GetWebhookSendsByKeycloakTypeAndIdRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * keycloak event type + */ + type: string; + /** + * keycloak event id + */ + kid: string; } export interface GetWebhooksRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * + */ + first?: number; + /** + * + */ + max?: number; +} + +export interface GetWebhooksCountRequest { + /** + * realm name (not id!) + */ realm: string; } +export interface ResendWebhookByIdRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * webhook id + */ + webhookId: string; + /** + * send id + */ + sendId: string; +} + export interface UpdateWebhookRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * webhook id + */ webhookId: string; + /** + * + */ webhookRepresentation: WebhookRepresentation; } @@ -61,9 +211,9 @@ export interface UpdateWebhookRequest { export class EventsApi extends runtime.BaseAPI { /** - * Create a new audit log event + * Creates request options for createEvent without sending the request */ - async createEventRaw(requestParameters: CreateEventRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async createEventRequestOpts(requestParameters: CreateEventRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -92,13 +242,25 @@ export class EventsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/events`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))), + + let urlPath = `/{realm}/events`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, method: 'POST', headers: headerParameters, query: queryParameters, body: EventRepresentationToJSON(requestParameters['eventRepresentation']), - }, initOverrides); + }; + } + + /** + * Create a new audit log event + */ + async createEventRaw(requestParameters: CreateEventRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.createEventRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -111,9 +273,9 @@ export class EventsApi extends runtime.BaseAPI { } /** - * Create a new webhook + * Creates request options for createWebhook without sending the request */ - async createWebhookRaw(requestParameters: CreateWebhookRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async createWebhookRequestOpts(requestParameters: CreateWebhookRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -142,13 +304,25 @@ export class EventsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/webhooks`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))), + + let urlPath = `/{realm}/webhooks`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, method: 'POST', headers: headerParameters, query: queryParameters, body: WebhookRepresentationToJSON(requestParameters['webhookRepresentation']), - }, initOverrides); + }; + } + + /** + * Create a new webhook + */ + async createWebhookRaw(requestParameters: CreateWebhookRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.createWebhookRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -161,9 +335,9 @@ export class EventsApi extends runtime.BaseAPI { } /** - * Delete the webhook + * Creates request options for deleteWebhook without sending the request */ - async deleteWebhookRaw(requestParameters: DeleteWebhookRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async deleteWebhookRequestOpts(requestParameters: DeleteWebhookRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -190,12 +364,25 @@ export class EventsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/webhooks/{webhookId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"webhookId"}}`, encodeURIComponent(String(requestParameters['webhookId']))), + + let urlPath = `/{realm}/webhooks/{webhookId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{webhookId}', encodeURIComponent(String(requestParameters['webhookId']))); + + return { + path: urlPath, method: 'DELETE', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Delete the webhook + */ + async deleteWebhookRaw(requestParameters: DeleteWebhookRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.deleteWebhookRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -208,9 +395,78 @@ export class EventsApi extends runtime.BaseAPI { } /** - * Get webhook by id + * Creates request options for getPayloadByKeycloakTypeAndId without sending the request */ - async getWebhookByIdRaw(requestParameters: GetWebhookByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async getPayloadByKeycloakTypeAndIdRequestOpts(requestParameters: GetPayloadByKeycloakTypeAndIdRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getPayloadByKeycloakTypeAndId().' + ); + } + + if (requestParameters['type'] == null) { + throw new runtime.RequiredError( + 'type', + 'Required parameter "type" was null or undefined when calling getPayloadByKeycloakTypeAndId().' + ); + } + + if (requestParameters['kid'] == null) { + throw new runtime.RequiredError( + 'kid', + 'Required parameter "kid" was null or undefined when calling getPayloadByKeycloakTypeAndId().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/webhooks/payload/{type}/{kid}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{type}', encodeURIComponent(String(requestParameters['type']))); + urlPath = urlPath.replace('{kid}', encodeURIComponent(String(requestParameters['kid']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get a payload by Keycloak type and id + */ + async getPayloadByKeycloakTypeAndIdRaw(requestParameters: GetPayloadByKeycloakTypeAndIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getPayloadByKeycloakTypeAndIdRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => EventRepresentationFromJSON(jsonValue)); + } + + /** + * Get a payload by Keycloak type and id + */ + async getPayloadByKeycloakTypeAndId(requestParameters: GetPayloadByKeycloakTypeAndIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getPayloadByKeycloakTypeAndIdRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getWebhookById without sending the request + */ + async getWebhookByIdRequestOpts(requestParameters: GetWebhookByIdRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -237,12 +493,25 @@ export class EventsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/webhooks/{webhookId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"webhookId"}}`, encodeURIComponent(String(requestParameters['webhookId']))), + + let urlPath = `/{realm}/webhooks/{webhookId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{webhookId}', encodeURIComponent(String(requestParameters['webhookId']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get webhook by id + */ + async getWebhookByIdRaw(requestParameters: GetWebhookByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getWebhookByIdRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => WebhookRepresentationFromJSON(jsonValue)); } @@ -256,10 +525,277 @@ export class EventsApi extends runtime.BaseAPI { } /** - * Get a list of webhooks for this realm - * Get webhooks + * Creates request options for getWebhookSecretById without sending the request */ - async getWebhooksRaw(requestParameters: GetWebhooksRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + async getWebhookSecretByIdRequestOpts(requestParameters: GetWebhookSecretByIdRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getWebhookSecretById().' + ); + } + + if (requestParameters['webhookId'] == null) { + throw new runtime.RequiredError( + 'webhookId', + 'Required parameter "webhookId" was null or undefined when calling getWebhookSecretById().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/webhooks/{webhookId}/secret`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{webhookId}', encodeURIComponent(String(requestParameters['webhookId']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get webhook secret by id + */ + async getWebhookSecretByIdRaw(requestParameters: GetWebhookSecretByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getWebhookSecretByIdRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => CredentialRepresentationFromJSON(jsonValue)); + } + + /** + * Get webhook secret by id + */ + async getWebhookSecretById(requestParameters: GetWebhookSecretByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getWebhookSecretByIdRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getWebhookSendById without sending the request + */ + async getWebhookSendByIdRequestOpts(requestParameters: GetWebhookSendByIdRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getWebhookSendById().' + ); + } + + if (requestParameters['webhookId'] == null) { + throw new runtime.RequiredError( + 'webhookId', + 'Required parameter "webhookId" was null or undefined when calling getWebhookSendById().' + ); + } + + if (requestParameters['sendId'] == null) { + throw new runtime.RequiredError( + 'sendId', + 'Required parameter "sendId" was null or undefined when calling getWebhookSendById().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/webhooks/{webhookId}/sends/{sendId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{webhookId}', encodeURIComponent(String(requestParameters['webhookId']))); + urlPath = urlPath.replace('{sendId}', encodeURIComponent(String(requestParameters['sendId']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get webhook send by id + */ + async getWebhookSendByIdRaw(requestParameters: GetWebhookSendByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getWebhookSendByIdRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => WebhookSendRepresentationFromJSON(jsonValue)); + } + + /** + * Get webhook send by id + */ + async getWebhookSendById(requestParameters: GetWebhookSendByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getWebhookSendByIdRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getWebhookSends without sending the request + */ + async getWebhookSendsRequestOpts(requestParameters: GetWebhookSendsRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getWebhookSends().' + ); + } + + if (requestParameters['webhookId'] == null) { + throw new runtime.RequiredError( + 'webhookId', + 'Required parameter "webhookId" was null or undefined when calling getWebhookSends().' + ); + } + + const queryParameters: any = {}; + + if (requestParameters['first'] != null) { + queryParameters['first'] = requestParameters['first']; + } + + if (requestParameters['max'] != null) { + queryParameters['max'] = requestParameters['max']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/webhooks/{webhookId}/sends`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{webhookId}', encodeURIComponent(String(requestParameters['webhookId']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get webhook sends + */ + async getWebhookSendsRaw(requestParameters: GetWebhookSendsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getWebhookSendsRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(WebhookSendRepresentationFromJSON)); + } + + /** + * Get webhook sends + */ + async getWebhookSends(requestParameters: GetWebhookSendsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const response = await this.getWebhookSendsRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getWebhookSendsByKeycloakTypeAndId without sending the request + */ + async getWebhookSendsByKeycloakTypeAndIdRequestOpts(requestParameters: GetWebhookSendsByKeycloakTypeAndIdRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getWebhookSendsByKeycloakTypeAndId().' + ); + } + + if (requestParameters['type'] == null) { + throw new runtime.RequiredError( + 'type', + 'Required parameter "type" was null or undefined when calling getWebhookSendsByKeycloakTypeAndId().' + ); + } + + if (requestParameters['kid'] == null) { + throw new runtime.RequiredError( + 'kid', + 'Required parameter "kid" was null or undefined when calling getWebhookSendsByKeycloakTypeAndId().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/webhooks/sends/{type}/{kid}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{type}', encodeURIComponent(String(requestParameters['type']))); + urlPath = urlPath.replace('{kid}', encodeURIComponent(String(requestParameters['kid']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get all webhook sends triggered by a Keycloak event + */ + async getWebhookSendsByKeycloakTypeAndIdRaw(requestParameters: GetWebhookSendsByKeycloakTypeAndIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getWebhookSendsByKeycloakTypeAndIdRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(WebhookSendRepresentationFromJSON)); + } + + /** + * Get all webhook sends triggered by a Keycloak event + */ + async getWebhookSendsByKeycloakTypeAndId(requestParameters: GetWebhookSendsByKeycloakTypeAndIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const response = await this.getWebhookSendsByKeycloakTypeAndIdRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getWebhooks without sending the request + */ + async getWebhooksRequestOpts(requestParameters: GetWebhooksRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -269,6 +805,14 @@ export class EventsApi extends runtime.BaseAPI { const queryParameters: any = {}; + if (requestParameters['first'] != null) { + queryParameters['first'] = requestParameters['first']; + } + + if (requestParameters['max'] != null) { + queryParameters['max'] = requestParameters['max']; + } + const headerParameters: runtime.HTTPHeaders = {}; if (this.configuration && this.configuration.accessToken) { @@ -279,12 +823,25 @@ export class EventsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/webhooks`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))), + + let urlPath = `/{realm}/webhooks`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get a list of webhooks for this realm + * Get webhooks + */ + async getWebhooksRaw(requestParameters: GetWebhooksRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getWebhooksRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(WebhookRepresentationFromJSON)); } @@ -299,9 +856,136 @@ export class EventsApi extends runtime.BaseAPI { } /** - * Update this webhook by id + * Creates request options for getWebhooksCount without sending the request */ - async updateWebhookRaw(requestParameters: UpdateWebhookRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async getWebhooksCountRequestOpts(requestParameters: GetWebhooksCountRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getWebhooksCount().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/webhooks/count`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get a count of webhooks. + * Get webhooks count + */ + async getWebhooksCountRaw(requestParameters: GetWebhooksCountRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getWebhooksCountRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + if (this.isJsonMime(response.headers.get('content-type'))) { + return new runtime.JSONApiResponse(response); + } else { + return new runtime.TextApiResponse(response) as any; + } + } + + /** + * Get a count of webhooks. + * Get webhooks count + */ + async getWebhooksCount(requestParameters: GetWebhooksCountRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getWebhooksCountRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for resendWebhookById without sending the request + */ + async resendWebhookByIdRequestOpts(requestParameters: ResendWebhookByIdRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling resendWebhookById().' + ); + } + + if (requestParameters['webhookId'] == null) { + throw new runtime.RequiredError( + 'webhookId', + 'Required parameter "webhookId" was null or undefined when calling resendWebhookById().' + ); + } + + if (requestParameters['sendId'] == null) { + throw new runtime.RequiredError( + 'sendId', + 'Required parameter "sendId" was null or undefined when calling resendWebhookById().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/webhooks/{webhookId}/sends/{sendId}/resend`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{webhookId}', encodeURIComponent(String(requestParameters['webhookId']))); + urlPath = urlPath.replace('{sendId}', encodeURIComponent(String(requestParameters['sendId']))); + + return { + path: urlPath, + method: 'POST', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Resend a webhook by send ID + */ + async resendWebhookByIdRaw(requestParameters: ResendWebhookByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.resendWebhookByIdRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Resend a webhook by send ID + */ + async resendWebhookById(requestParameters: ResendWebhookByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.resendWebhookByIdRaw(requestParameters, initOverrides); + } + + /** + * Creates request options for updateWebhook without sending the request + */ + async updateWebhookRequestOpts(requestParameters: UpdateWebhookRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -337,13 +1021,26 @@ export class EventsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/webhooks/{webhookId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"webhookId"}}`, encodeURIComponent(String(requestParameters['webhookId']))), + + let urlPath = `/{realm}/webhooks/{webhookId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{webhookId}', encodeURIComponent(String(requestParameters['webhookId']))); + + return { + path: urlPath, method: 'PUT', headers: headerParameters, query: queryParameters, body: WebhookRepresentationToJSON(requestParameters['webhookRepresentation']), - }, initOverrides); + }; + } + + /** + * Update this webhook by id + */ + async updateWebhookRaw(requestParameters: UpdateWebhookRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.updateWebhookRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/IdentityProvidersApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/IdentityProvidersApi.ts index df21178..c2682c3 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/IdentityProvidersApi.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/IdentityProvidersApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -12,86 +12,231 @@ * Do not edit the class manually. */ - import * as runtime from '../runtime'; -import type { - IdentityProviderMapperRepresentation, - IdentityProviderRepresentation, -} from '../models/index'; import { + type IdentityProviderMapperRepresentation, IdentityProviderMapperRepresentationFromJSON, IdentityProviderMapperRepresentationToJSON, +} from '../models/IdentityProviderMapperRepresentation'; +import { + type IdentityProviderRepresentation, IdentityProviderRepresentationFromJSON, IdentityProviderRepresentationToJSON, -} from '../models/index'; +} from '../models/IdentityProviderRepresentation'; +import { + type LinkIdentityProviderRepresentation, + LinkIdentityProviderRepresentationFromJSON, + LinkIdentityProviderRepresentationToJSON, +} from '../models/LinkIdentityProviderRepresentation'; export interface AddIdpMapperRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ alias: string; + /** + * + */ identityProviderMapperRepresentation: IdentityProviderMapperRepresentation; } export interface CreateIdpRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ identityProviderRepresentation: IdentityProviderRepresentation; } export interface DeleteIdpRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * Identity Provider alias + */ alias: string; } export interface DeleteIdpMapperRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ alias: string; + /** + * Mapper id + */ id: string; } export interface GetIdpRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * Identity Provider alias + */ alias: string; } export interface GetIdpMapperRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ alias: string; + /** + * Mapper id + */ id: string; } export interface GetIdpMappersRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ alias: string; } export interface GetIdpsRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; } export interface ImportIdpJsonRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; +} + +export interface LinkIdpRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ + linkIdentityProviderRepresentation: LinkIdentityProviderRepresentation; +} + +export interface UnlinkIdpRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * idp alias + */ + alias: string; } export interface UpdateIdpRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * Identity Provider alias + */ alias: string; + /** + * + */ identityProviderRepresentation: IdentityProviderRepresentation; } export interface UpdateIdpMapperRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ alias: string; + /** + * Mapper id + */ id: string; + /** + * + */ identityProviderMapperRepresentation: IdentityProviderMapperRepresentation; } @@ -101,9 +246,9 @@ export interface UpdateIdpMapperRequest { export class IdentityProvidersApi extends runtime.BaseAPI { /** - * Add a mapper to identity provider + * Creates request options for addIdpMapper without sending the request */ - async addIdpMapperRaw(requestParameters: AddIdpMapperRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async addIdpMapperRequestOpts(requestParameters: AddIdpMapperRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -146,13 +291,27 @@ export class IdentityProvidersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/idps/{alias}/mappers`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"alias"}}`, encodeURIComponent(String(requestParameters['alias']))), + + let urlPath = `/{realm}/orgs/{orgId}/idps/{alias}/mappers`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{alias}', encodeURIComponent(String(requestParameters['alias']))); + + return { + path: urlPath, method: 'POST', headers: headerParameters, query: queryParameters, body: IdentityProviderMapperRepresentationToJSON(requestParameters['identityProviderMapperRepresentation']), - }, initOverrides); + }; + } + + /** + * Add a mapper to identity provider + */ + async addIdpMapperRaw(requestParameters: AddIdpMapperRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.addIdpMapperRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -165,9 +324,9 @@ export class IdentityProvidersApi extends runtime.BaseAPI { } /** - * Create a new identity provider for this organization + * Creates request options for createIdp without sending the request */ - async createIdpRaw(requestParameters: CreateIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async createIdpRequestOpts(requestParameters: CreateIdpRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -203,13 +362,26 @@ export class IdentityProvidersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/idps`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/orgs/{orgId}/idps`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'POST', headers: headerParameters, query: queryParameters, body: IdentityProviderRepresentationToJSON(requestParameters['identityProviderRepresentation']), - }, initOverrides); + }; + } + + /** + * Create a new identity provider for this organization + */ + async createIdpRaw(requestParameters: CreateIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.createIdpRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -222,9 +394,9 @@ export class IdentityProvidersApi extends runtime.BaseAPI { } /** - * Delete the identity provider + * Creates request options for deleteIdp without sending the request */ - async deleteIdpRaw(requestParameters: DeleteIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async deleteIdpRequestOpts(requestParameters: DeleteIdpRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -258,12 +430,26 @@ export class IdentityProvidersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/idps/{alias}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"alias"}}`, encodeURIComponent(String(requestParameters['alias']))), + + let urlPath = `/{realm}/orgs/{orgId}/idps/{alias}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{alias}', encodeURIComponent(String(requestParameters['alias']))); + + return { + path: urlPath, method: 'DELETE', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Delete the identity provider + */ + async deleteIdpRaw(requestParameters: DeleteIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.deleteIdpRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -276,9 +462,9 @@ export class IdentityProvidersApi extends runtime.BaseAPI { } /** - * Delete a mapper for the identity provider + * Creates request options for deleteIdpMapper without sending the request */ - async deleteIdpMapperRaw(requestParameters: DeleteIdpMapperRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async deleteIdpMapperRequestOpts(requestParameters: DeleteIdpMapperRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -319,12 +505,27 @@ export class IdentityProvidersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/idps/{alias}/mappers/{id}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"alias"}}`, encodeURIComponent(String(requestParameters['alias']))).replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + + let urlPath = `/{realm}/orgs/{orgId}/idps/{alias}/mappers/{id}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{alias}', encodeURIComponent(String(requestParameters['alias']))); + urlPath = urlPath.replace('{id}', encodeURIComponent(String(requestParameters['id']))); + + return { + path: urlPath, method: 'DELETE', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Delete a mapper for the identity provider + */ + async deleteIdpMapperRaw(requestParameters: DeleteIdpMapperRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.deleteIdpMapperRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -337,9 +538,9 @@ export class IdentityProvidersApi extends runtime.BaseAPI { } /** - * Get identity provider for this organization by alias + * Creates request options for getIdp without sending the request */ - async getIdpRaw(requestParameters: GetIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async getIdpRequestOpts(requestParameters: GetIdpRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -373,12 +574,26 @@ export class IdentityProvidersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/idps/{alias}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"alias"}}`, encodeURIComponent(String(requestParameters['alias']))), + + let urlPath = `/{realm}/orgs/{orgId}/idps/{alias}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{alias}', encodeURIComponent(String(requestParameters['alias']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get identity provider for this organization by alias + */ + async getIdpRaw(requestParameters: GetIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getIdpRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => IdentityProviderRepresentationFromJSON(jsonValue)); } @@ -392,9 +607,9 @@ export class IdentityProvidersApi extends runtime.BaseAPI { } /** - * Get mapper by id for the identity provider + * Creates request options for getIdpMapper without sending the request */ - async getIdpMapperRaw(requestParameters: GetIdpMapperRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async getIdpMapperRequestOpts(requestParameters: GetIdpMapperRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -435,12 +650,27 @@ export class IdentityProvidersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/idps/{alias}/mappers/{id}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"alias"}}`, encodeURIComponent(String(requestParameters['alias']))).replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + + let urlPath = `/{realm}/orgs/{orgId}/idps/{alias}/mappers/{id}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{alias}', encodeURIComponent(String(requestParameters['alias']))); + urlPath = urlPath.replace('{id}', encodeURIComponent(String(requestParameters['id']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get mapper by id for the identity provider + */ + async getIdpMapperRaw(requestParameters: GetIdpMapperRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getIdpMapperRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => IdentityProviderMapperRepresentationFromJSON(jsonValue)); } @@ -454,9 +684,9 @@ export class IdentityProvidersApi extends runtime.BaseAPI { } /** - * Get mappers for identity provider + * Creates request options for getIdpMappers without sending the request */ - async getIdpMappersRaw(requestParameters: GetIdpMappersRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + async getIdpMappersRequestOpts(requestParameters: GetIdpMappersRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -490,12 +720,26 @@ export class IdentityProvidersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/idps/{alias}/mappers`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"alias"}}`, encodeURIComponent(String(requestParameters['alias']))), + + let urlPath = `/{realm}/orgs/{orgId}/idps/{alias}/mappers`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{alias}', encodeURIComponent(String(requestParameters['alias']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get mappers for identity provider + */ + async getIdpMappersRaw(requestParameters: GetIdpMappersRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getIdpMappersRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(IdentityProviderMapperRepresentationFromJSON)); } @@ -509,9 +753,9 @@ export class IdentityProvidersApi extends runtime.BaseAPI { } /** - * Get identity providers for this organization + * Creates request options for getIdps without sending the request */ - async getIdpsRaw(requestParameters: GetIdpsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + async getIdpsRequestOpts(requestParameters: GetIdpsRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -538,12 +782,25 @@ export class IdentityProvidersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/idps`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/orgs/{orgId}/idps`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get identity providers for this organization + */ + async getIdpsRaw(requestParameters: GetIdpsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getIdpsRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(IdentityProviderRepresentationFromJSON)); } @@ -557,9 +814,9 @@ export class IdentityProvidersApi extends runtime.BaseAPI { } /** - * Import identity provider from uploaded JSON file + * Creates request options for importIdpJson without sending the request */ - async importIdpJsonRaw(requestParameters: ImportIdpJsonRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async importIdpJsonRequestOpts(requestParameters: ImportIdpJsonRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -586,12 +843,25 @@ export class IdentityProvidersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/idps/import-config`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/orgs/{orgId}/idps/import-config`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'POST', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Import identity provider from uploaded JSON file + */ + async importIdpJsonRaw(requestParameters: ImportIdpJsonRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.importIdpJsonRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response); } @@ -605,9 +875,147 @@ export class IdentityProvidersApi extends runtime.BaseAPI { } /** - * Update identity provider for this organization by alias + * Creates request options for linkIdp without sending the request */ - async updateIdpRaw(requestParameters: UpdateIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async linkIdpRequestOpts(requestParameters: LinkIdpRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling linkIdp().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling linkIdp().' + ); + } + + if (requestParameters['linkIdentityProviderRepresentation'] == null) { + throw new runtime.RequiredError( + 'linkIdentityProviderRepresentation', + 'Required parameter "linkIdentityProviderRepresentation" was null or undefined when calling linkIdp().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/idps/link`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: LinkIdentityProviderRepresentationToJSON(requestParameters['linkIdentityProviderRepresentation']), + }; + } + + /** + * Link an existing identity provider to this organization + */ + async linkIdpRaw(requestParameters: LinkIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.linkIdpRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Link an existing identity provider to this organization + */ + async linkIdp(requestParameters: LinkIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.linkIdpRaw(requestParameters, initOverrides); + } + + /** + * Creates request options for unlinkIdp without sending the request + */ + async unlinkIdpRequestOpts(requestParameters: UnlinkIdpRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling unlinkIdp().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling unlinkIdp().' + ); + } + + if (requestParameters['alias'] == null) { + throw new runtime.RequiredError( + 'alias', + 'Required parameter "alias" was null or undefined when calling unlinkIdp().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/idps/{alias}/unlink`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{alias}', encodeURIComponent(String(requestParameters['alias']))); + + return { + path: urlPath, + method: 'POST', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Unlink an existing and linked identity provider from this organization + */ + async unlinkIdpRaw(requestParameters: UnlinkIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.unlinkIdpRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Unlink an existing and linked identity provider from this organization + */ + async unlinkIdp(requestParameters: UnlinkIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.unlinkIdpRaw(requestParameters, initOverrides); + } + + /** + * Creates request options for updateIdp without sending the request + */ + async updateIdpRequestOpts(requestParameters: UpdateIdpRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -650,13 +1058,27 @@ export class IdentityProvidersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/idps/{alias}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"alias"}}`, encodeURIComponent(String(requestParameters['alias']))), + + let urlPath = `/{realm}/orgs/{orgId}/idps/{alias}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{alias}', encodeURIComponent(String(requestParameters['alias']))); + + return { + path: urlPath, method: 'PUT', headers: headerParameters, query: queryParameters, body: IdentityProviderRepresentationToJSON(requestParameters['identityProviderRepresentation']), - }, initOverrides); + }; + } + + /** + * Update identity provider for this organization by alias + */ + async updateIdpRaw(requestParameters: UpdateIdpRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.updateIdpRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -669,9 +1091,9 @@ export class IdentityProvidersApi extends runtime.BaseAPI { } /** - * Update a mapper for the identity provider + * Creates request options for updateIdpMapper without sending the request */ - async updateIdpMapperRaw(requestParameters: UpdateIdpMapperRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async updateIdpMapperRequestOpts(requestParameters: UpdateIdpMapperRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -721,13 +1143,28 @@ export class IdentityProvidersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/idps/{alias}/mappers/{id}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"alias"}}`, encodeURIComponent(String(requestParameters['alias']))).replace(`{${"id"}}`, encodeURIComponent(String(requestParameters['id']))), + + let urlPath = `/{realm}/orgs/{orgId}/idps/{alias}/mappers/{id}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{alias}', encodeURIComponent(String(requestParameters['alias']))); + urlPath = urlPath.replace('{id}', encodeURIComponent(String(requestParameters['id']))); + + return { + path: urlPath, method: 'PUT', headers: headerParameters, query: queryParameters, body: IdentityProviderMapperRepresentationToJSON(requestParameters['identityProviderMapperRepresentation']), - }, initOverrides); + }; + } + + /** + * Update a mapper for the identity provider + */ + async updateIdpMapperRaw(requestParameters: UpdateIdpMapperRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.updateIdpMapperRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationApi.ts new file mode 100644 index 0000000..3378ab1 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationApi.ts @@ -0,0 +1,183 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import * as runtime from '../runtime'; +import { + type OrganizationDomainRepresentation, + OrganizationDomainRepresentationFromJSON, + OrganizationDomainRepresentationToJSON, +} from '../models/OrganizationDomainRepresentation'; + +export interface GetOrganizationDomainRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * domain name + */ + domainName: string; +} + +export interface GetOrganizationDomainsRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; +} + +/** + * + */ +export class OrganizationApi extends runtime.BaseAPI { + + /** + * Creates request options for getOrganizationDomain without sending the request + */ + async getOrganizationDomainRequestOpts(requestParameters: GetOrganizationDomainRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getOrganizationDomain().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling getOrganizationDomain().' + ); + } + + if (requestParameters['domainName'] == null) { + throw new runtime.RequiredError( + 'domainName', + 'Required parameter "domainName" was null or undefined when calling getOrganizationDomain().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/domains/{domainName}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{domainName}', encodeURIComponent(String(requestParameters['domainName']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get details for a domain owned by an organization + */ + async getOrganizationDomainRaw(requestParameters: GetOrganizationDomainRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getOrganizationDomainRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => OrganizationDomainRepresentationFromJSON(jsonValue)); + } + + /** + * Get details for a domain owned by an organization + */ + async getOrganizationDomain(requestParameters: GetOrganizationDomainRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getOrganizationDomainRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getOrganizationDomains without sending the request + */ + async getOrganizationDomainsRequestOpts(requestParameters: GetOrganizationDomainsRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getOrganizationDomains().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling getOrganizationDomains().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/domains`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get details for all domains owned by an organization + */ + async getOrganizationDomainsRaw(requestParameters: GetOrganizationDomainsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getOrganizationDomainsRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(OrganizationDomainRepresentationFromJSON)); + } + + /** + * Get details for all domains owned by an organization + */ + async getOrganizationDomains(requestParameters: GetOrganizationDomainsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const response = await this.getOrganizationDomainsRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationDomainsApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationDomainsApi.ts index 9b72e86..5fe73b9 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationDomainsApi.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationDomainsApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -12,30 +12,20 @@ * Do not edit the class manually. */ - import * as runtime from '../runtime'; -import type { - OrganizationDomainRepresentation, -} from '../models/index'; -import { - OrganizationDomainRepresentationFromJSON, - OrganizationDomainRepresentationToJSON, -} from '../models/index'; - -export interface GetOrganizationDomainRequest { - realm: string; - orgId: string; - domainName: string; -} - -export interface GetOrganizationDomainsRequest { - realm: string; - orgId: string; -} export interface VerifyDomainRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * domain name + */ domainName: string; } @@ -45,27 +35,27 @@ export interface VerifyDomainRequest { export class OrganizationDomainsApi extends runtime.BaseAPI { /** - * Get details for a domain owned by an organization + * Creates request options for verifyDomain without sending the request */ - async getOrganizationDomainRaw(requestParameters: GetOrganizationDomainRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async verifyDomainRequestOpts(requestParameters: VerifyDomainRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', - 'Required parameter "realm" was null or undefined when calling getOrganizationDomain().' + 'Required parameter "realm" was null or undefined when calling verifyDomain().' ); } if (requestParameters['orgId'] == null) { throw new runtime.RequiredError( 'orgId', - 'Required parameter "orgId" was null or undefined when calling getOrganizationDomain().' + 'Required parameter "orgId" was null or undefined when calling verifyDomain().' ); } if (requestParameters['domainName'] == null) { throw new runtime.RequiredError( 'domainName', - 'Required parameter "domainName" was null or undefined when calling getOrganizationDomain().' + 'Required parameter "domainName" was null or undefined when calling verifyDomain().' ); } @@ -81,70 +71,18 @@ export class OrganizationDomainsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/domains/{domainName}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"domainName"}}`, encodeURIComponent(String(requestParameters['domainName']))), - method: 'GET', - headers: headerParameters, - query: queryParameters, - }, initOverrides); - - return new runtime.JSONApiResponse(response, (jsonValue) => OrganizationDomainRepresentationFromJSON(jsonValue)); - } - /** - * Get details for a domain owned by an organization - */ - async getOrganizationDomain(requestParameters: GetOrganizationDomainRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { - const response = await this.getOrganizationDomainRaw(requestParameters, initOverrides); - return await response.value(); - } - - /** - * Get details for all domains owned by an organization - */ - async getOrganizationDomainsRaw(requestParameters: GetOrganizationDomainsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { - if (requestParameters['realm'] == null) { - throw new runtime.RequiredError( - 'realm', - 'Required parameter "realm" was null or undefined when calling getOrganizationDomains().' - ); - } - - if (requestParameters['orgId'] == null) { - throw new runtime.RequiredError( - 'orgId', - 'Required parameter "orgId" was null or undefined when calling getOrganizationDomains().' - ); - } - - const queryParameters: any = {}; - - const headerParameters: runtime.HTTPHeaders = {}; - - if (this.configuration && this.configuration.accessToken) { - const token = this.configuration.accessToken; - const tokenString = await token("access_token", []); + let urlPath = `/{realm}/orgs/{orgId}/domains/{domainName}/verify`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{domainName}', encodeURIComponent(String(requestParameters['domainName']))); - if (tokenString) { - headerParameters["Authorization"] = `Bearer ${tokenString}`; - } - } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/domains`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), - method: 'GET', + return { + path: urlPath, + method: 'POST', headers: headerParameters, query: queryParameters, - }, initOverrides); - - return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(OrganizationDomainRepresentationFromJSON)); - } - - /** - * Get details for all domains owned by an organization - */ - async getOrganizationDomains(requestParameters: GetOrganizationDomainsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { - const response = await this.getOrganizationDomainsRaw(requestParameters, initOverrides); - return await response.value(); + }; } /** @@ -152,45 +90,8 @@ export class OrganizationDomainsApi extends runtime.BaseAPI { * Start domain verification */ async verifyDomainRaw(requestParameters: VerifyDomainRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { - if (requestParameters['realm'] == null) { - throw new runtime.RequiredError( - 'realm', - 'Required parameter "realm" was null or undefined when calling verifyDomain().' - ); - } - - if (requestParameters['orgId'] == null) { - throw new runtime.RequiredError( - 'orgId', - 'Required parameter "orgId" was null or undefined when calling verifyDomain().' - ); - } - - if (requestParameters['domainName'] == null) { - throw new runtime.RequiredError( - 'domainName', - 'Required parameter "domainName" was null or undefined when calling verifyDomain().' - ); - } - - const queryParameters: any = {}; - - const headerParameters: runtime.HTTPHeaders = {}; - - if (this.configuration && this.configuration.accessToken) { - const token = this.configuration.accessToken; - const tokenString = await token("access_token", []); - - if (tokenString) { - headerParameters["Authorization"] = `Bearer ${tokenString}`; - } - } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/domains/{domainName}/verify`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"domainName"}}`, encodeURIComponent(String(requestParameters['domainName']))), - method: 'POST', - headers: headerParameters, - query: queryParameters, - }, initOverrides); + const requestOptions = await this.verifyDomainRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationInvitationApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationInvitationApi.ts new file mode 100644 index 0000000..3592d93 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationInvitationApi.ts @@ -0,0 +1,549 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import * as runtime from '../runtime'; +import { + type InvitationRepresentation, + InvitationRepresentationFromJSON, + InvitationRepresentationToJSON, +} from '../models/InvitationRepresentation'; +import { + type InvitationRequestRepresentation, + InvitationRequestRepresentationFromJSON, + InvitationRequestRepresentationToJSON, +} from '../models/InvitationRequestRepresentation'; + +export interface AddOrganizationInvitationRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * + */ + invitationRequestRepresentation: InvitationRequestRepresentation; +} + +export interface GetOrganizationInvitationByIdRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * invitation id + */ + invitationId: string; +} + +export interface GetOrganizationInvitationCountRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; +} + +export interface GetOrganizationInvitationsRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * + */ + search?: string; + /** + * + */ + first?: number; + /** + * + */ + max?: number; +} + +export interface RemoveOrganizationInvitationRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * invitation id + */ + invitationId: string; +} + +export interface ResendOrganizationInvitationRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * invitation id + */ + invitationId: string; +} + +/** + * + */ +export class OrganizationInvitationApi extends runtime.BaseAPI { + + /** + * Creates request options for addOrganizationInvitation without sending the request + */ + async addOrganizationInvitationRequestOpts(requestParameters: AddOrganizationInvitationRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling addOrganizationInvitation().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling addOrganizationInvitation().' + ); + } + + if (requestParameters['invitationRequestRepresentation'] == null) { + throw new runtime.RequiredError( + 'invitationRequestRepresentation', + 'Required parameter "invitationRequestRepresentation" was null or undefined when calling addOrganizationInvitation().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/invitations`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: InvitationRequestRepresentationToJSON(requestParameters['invitationRequestRepresentation']), + }; + } + + /** + * Create an invitation to join the specified organization. Requires a user to register with the application (if they don\'t already have an account) before they can accept the invitation. Acceptance happens during login via a required action. + * Create an invitation to an organization + */ + async addOrganizationInvitationRaw(requestParameters: AddOrganizationInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.addOrganizationInvitationRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Create an invitation to join the specified organization. Requires a user to register with the application (if they don\'t already have an account) before they can accept the invitation. Acceptance happens during login via a required action. + * Create an invitation to an organization + */ + async addOrganizationInvitation(requestParameters: AddOrganizationInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.addOrganizationInvitationRaw(requestParameters, initOverrides); + } + + /** + * Creates request options for getOrganizationInvitationById without sending the request + */ + async getOrganizationInvitationByIdRequestOpts(requestParameters: GetOrganizationInvitationByIdRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getOrganizationInvitationById().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling getOrganizationInvitationById().' + ); + } + + if (requestParameters['invitationId'] == null) { + throw new runtime.RequiredError( + 'invitationId', + 'Required parameter "invitationId" was null or undefined when calling getOrganizationInvitationById().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/invitations/{invitationId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{invitationId}', encodeURIComponent(String(requestParameters['invitationId']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get an invitation to an organization by its uuid. + * Get organization invitation by ID + */ + async getOrganizationInvitationByIdRaw(requestParameters: GetOrganizationInvitationByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getOrganizationInvitationByIdRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => InvitationRepresentationFromJSON(jsonValue)); + } + + /** + * Get an invitation to an organization by its uuid. + * Get organization invitation by ID + */ + async getOrganizationInvitationById(requestParameters: GetOrganizationInvitationByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getOrganizationInvitationByIdRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getOrganizationInvitationCount without sending the request + */ + async getOrganizationInvitationCountRequestOpts(requestParameters: GetOrganizationInvitationCountRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getOrganizationInvitationCount().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling getOrganizationInvitationCount().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/invitations/count`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get a count of invitations to an organization + * Get organization invitation count + */ + async getOrganizationInvitationCountRaw(requestParameters: GetOrganizationInvitationCountRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getOrganizationInvitationCountRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + if (this.isJsonMime(response.headers.get('content-type'))) { + return new runtime.JSONApiResponse(response); + } else { + return new runtime.TextApiResponse(response) as any; + } + } + + /** + * Get a count of invitations to an organization + * Get organization invitation count + */ + async getOrganizationInvitationCount(requestParameters: GetOrganizationInvitationCountRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getOrganizationInvitationCountRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getOrganizationInvitations without sending the request + */ + async getOrganizationInvitationsRequestOpts(requestParameters: GetOrganizationInvitationsRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getOrganizationInvitations().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling getOrganizationInvitations().' + ); + } + + const queryParameters: any = {}; + + if (requestParameters['search'] != null) { + queryParameters['search'] = requestParameters['search']; + } + + if (requestParameters['first'] != null) { + queryParameters['first'] = requestParameters['first']; + } + + if (requestParameters['max'] != null) { + queryParameters['max'] = requestParameters['max']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/invitations`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get a paginated list of invitations to an organization, using an optional search query for email address. + * Get organization invitations + */ + async getOrganizationInvitationsRaw(requestParameters: GetOrganizationInvitationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getOrganizationInvitationsRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(InvitationRepresentationFromJSON)); + } + + /** + * Get a paginated list of invitations to an organization, using an optional search query for email address. + * Get organization invitations + */ + async getOrganizationInvitations(requestParameters: GetOrganizationInvitationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const response = await this.getOrganizationInvitationsRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for removeOrganizationInvitation without sending the request + */ + async removeOrganizationInvitationRequestOpts(requestParameters: RemoveOrganizationInvitationRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling removeOrganizationInvitation().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling removeOrganizationInvitation().' + ); + } + + if (requestParameters['invitationId'] == null) { + throw new runtime.RequiredError( + 'invitationId', + 'Required parameter "invitationId" was null or undefined when calling removeOrganizationInvitation().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/invitations/{invitationId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{invitationId}', encodeURIComponent(String(requestParameters['invitationId']))); + + return { + path: urlPath, + method: 'DELETE', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Remove a pending invitation + */ + async removeOrganizationInvitationRaw(requestParameters: RemoveOrganizationInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.removeOrganizationInvitationRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Remove a pending invitation + */ + async removeOrganizationInvitation(requestParameters: RemoveOrganizationInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.removeOrganizationInvitationRaw(requestParameters, initOverrides); + } + + /** + * Creates request options for resendOrganizationInvitation without sending the request + */ + async resendOrganizationInvitationRequestOpts(requestParameters: ResendOrganizationInvitationRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling resendOrganizationInvitation().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling resendOrganizationInvitation().' + ); + } + + if (requestParameters['invitationId'] == null) { + throw new runtime.RequiredError( + 'invitationId', + 'Required parameter "invitationId" was null or undefined when calling resendOrganizationInvitation().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/invitations/{invitationId}/resend-email`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{invitationId}', encodeURIComponent(String(requestParameters['invitationId']))); + + return { + path: urlPath, + method: 'PUT', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Resend the email for an existing Organization Invitation + * Resend an Organization Invitation + */ + async resendOrganizationInvitationRaw(requestParameters: ResendOrganizationInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.resendOrganizationInvitationRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Resend the email for an existing Organization Invitation + * Resend an Organization Invitation + */ + async resendOrganizationInvitation(requestParameters: ResendOrganizationInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.resendOrganizationInvitationRaw(requestParameters, initOverrides); + } + +} diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationInvitationsApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationInvitationsApi.ts deleted file mode 100644 index 7565fde..0000000 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationInvitationsApi.ts +++ /dev/null @@ -1,226 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - - -import * as runtime from '../runtime'; -import type { - InvitationRepresentation, - InvitationRequestRepresentation, -} from '../models/index'; -import { - InvitationRepresentationFromJSON, - InvitationRepresentationToJSON, - InvitationRequestRepresentationFromJSON, - InvitationRequestRepresentationToJSON, -} from '../models/index'; - -export interface AddOrganizationInvitationRequest { - realm: string; - orgId: string; - invitationRequestRepresentation: InvitationRequestRepresentation; -} - -export interface GetOrganizationInvitationsRequest { - realm: string; - orgId: string; - search?: string; - first?: number; - max?: number; -} - -export interface RemoveOrganizationInvitationRequest { - realm: string; - orgId: string; - invitationId: string; -} - -/** - * - */ -export class OrganizationInvitationsApi extends runtime.BaseAPI { - - /** - * Create an invitation to an organization - */ - async addOrganizationInvitationRaw(requestParameters: AddOrganizationInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { - if (requestParameters['realm'] == null) { - throw new runtime.RequiredError( - 'realm', - 'Required parameter "realm" was null or undefined when calling addOrganizationInvitation().' - ); - } - - if (requestParameters['orgId'] == null) { - throw new runtime.RequiredError( - 'orgId', - 'Required parameter "orgId" was null or undefined when calling addOrganizationInvitation().' - ); - } - - if (requestParameters['invitationRequestRepresentation'] == null) { - throw new runtime.RequiredError( - 'invitationRequestRepresentation', - 'Required parameter "invitationRequestRepresentation" was null or undefined when calling addOrganizationInvitation().' - ); - } - - const queryParameters: any = {}; - - const headerParameters: runtime.HTTPHeaders = {}; - - headerParameters['Content-Type'] = 'application/json'; - - if (this.configuration && this.configuration.accessToken) { - const token = this.configuration.accessToken; - const tokenString = await token("access_token", []); - - if (tokenString) { - headerParameters["Authorization"] = `Bearer ${tokenString}`; - } - } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/invitations`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), - method: 'POST', - headers: headerParameters, - query: queryParameters, - body: InvitationRequestRepresentationToJSON(requestParameters['invitationRequestRepresentation']), - }, initOverrides); - - return new runtime.VoidApiResponse(response); - } - - /** - * Create an invitation to an organization - */ - async addOrganizationInvitation(requestParameters: AddOrganizationInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { - await this.addOrganizationInvitationRaw(requestParameters, initOverrides); - } - - /** - * Get a paginated list of invitations to an organization, using an optional search query for email address. - * Get organization invitations - */ - async getOrganizationInvitationsRaw(requestParameters: GetOrganizationInvitationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { - if (requestParameters['realm'] == null) { - throw new runtime.RequiredError( - 'realm', - 'Required parameter "realm" was null or undefined when calling getOrganizationInvitations().' - ); - } - - if (requestParameters['orgId'] == null) { - throw new runtime.RequiredError( - 'orgId', - 'Required parameter "orgId" was null or undefined when calling getOrganizationInvitations().' - ); - } - - const queryParameters: any = {}; - - if (requestParameters['search'] != null) { - queryParameters['search'] = requestParameters['search']; - } - - if (requestParameters['first'] != null) { - queryParameters['first'] = requestParameters['first']; - } - - if (requestParameters['max'] != null) { - queryParameters['max'] = requestParameters['max']; - } - - const headerParameters: runtime.HTTPHeaders = {}; - - if (this.configuration && this.configuration.accessToken) { - const token = this.configuration.accessToken; - const tokenString = await token("access_token", []); - - if (tokenString) { - headerParameters["Authorization"] = `Bearer ${tokenString}`; - } - } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/invitations`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), - method: 'GET', - headers: headerParameters, - query: queryParameters, - }, initOverrides); - - return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(InvitationRepresentationFromJSON)); - } - - /** - * Get a paginated list of invitations to an organization, using an optional search query for email address. - * Get organization invitations - */ - async getOrganizationInvitations(requestParameters: GetOrganizationInvitationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { - const response = await this.getOrganizationInvitationsRaw(requestParameters, initOverrides); - return await response.value(); - } - - /** - * Remove a pending invitation - */ - async removeOrganizationInvitationRaw(requestParameters: RemoveOrganizationInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { - if (requestParameters['realm'] == null) { - throw new runtime.RequiredError( - 'realm', - 'Required parameter "realm" was null or undefined when calling removeOrganizationInvitation().' - ); - } - - if (requestParameters['orgId'] == null) { - throw new runtime.RequiredError( - 'orgId', - 'Required parameter "orgId" was null or undefined when calling removeOrganizationInvitation().' - ); - } - - if (requestParameters['invitationId'] == null) { - throw new runtime.RequiredError( - 'invitationId', - 'Required parameter "invitationId" was null or undefined when calling removeOrganizationInvitation().' - ); - } - - const queryParameters: any = {}; - - const headerParameters: runtime.HTTPHeaders = {}; - - if (this.configuration && this.configuration.accessToken) { - const token = this.configuration.accessToken; - const tokenString = await token("access_token", []); - - if (tokenString) { - headerParameters["Authorization"] = `Bearer ${tokenString}`; - } - } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/invitations/{invitationId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"invitationId"}}`, encodeURIComponent(String(requestParameters['invitationId']))), - method: 'DELETE', - headers: headerParameters, - query: queryParameters, - }, initOverrides); - - return new runtime.VoidApiResponse(response); - } - - /** - * Remove a pending invitation - */ - async removeOrganizationInvitation(requestParameters: RemoveOrganizationInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { - await this.removeOrganizationInvitationRaw(requestParameters, initOverrides); - } - -} diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationMembershipsApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationMembershipsApi.ts index 53defc7..8e0b3c8 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationMembershipsApi.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationMembershipsApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -12,44 +12,140 @@ * Do not edit the class manually. */ - import * as runtime from '../runtime'; -import type { - UserRepresentation, -} from '../models/index'; import { - UserRepresentationFromJSON, - UserRepresentationToJSON, -} from '../models/index'; + type OrganizationMemberAttributeRepresentation, + OrganizationMemberAttributeRepresentationFromJSON, + OrganizationMemberAttributeRepresentationToJSON, +} from '../models/OrganizationMemberAttributeRepresentation'; +import { + type UserWithOrgsBriefRepresentation, + UserWithOrgsBriefRepresentationFromJSON, + UserWithOrgsBriefRepresentationToJSON, +} from '../models/UserWithOrgsBriefRepresentation'; export interface AddOrganizationMemberRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * user id + */ userId: string; } +export interface AddOrganizationMemberAttributesRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * user id + */ + userId: string; + /** + * + */ + organizationMemberAttributeRepresentation: OrganizationMemberAttributeRepresentation; +} + export interface CheckOrganizationMembershipRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * user id + */ + userId: string; +} + +export interface GetOrganizationMemberAttributesRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * user id + */ userId: string; } export interface GetOrganizationMembershipsRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ search?: string; + /** + * + */ first?: number; + /** + * + */ max?: number; + /** + * + */ + excludeAdminAccounts?: boolean; + /** + * + */ + includeOrgs?: boolean; } export interface GetOrganizationMembershipsCountRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ + excludeAdminAccounts?: boolean; } export interface RemoveOrganizationMemberRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * user id + */ userId: string; } @@ -59,10 +155,9 @@ export interface RemoveOrganizationMemberRequest { export class OrganizationMembershipsApi extends runtime.BaseAPI { /** - * Add the specified user to the specified organization as a member - * Add an organization member + * Creates request options for addOrganizationMember without sending the request */ - async addOrganizationMemberRaw(requestParameters: AddOrganizationMemberRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async addOrganizationMemberRequestOpts(requestParameters: AddOrganizationMemberRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -96,12 +191,27 @@ export class OrganizationMembershipsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/members/{userId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"userId"}}`, encodeURIComponent(String(requestParameters['userId']))), + + let urlPath = `/{realm}/orgs/{orgId}/members/{userId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + + return { + path: urlPath, method: 'PUT', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Add the specified user to the specified organization as a member + * Add an organization member + */ + async addOrganizationMemberRaw(requestParameters: AddOrganizationMemberRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.addOrganizationMemberRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -115,9 +225,90 @@ export class OrganizationMembershipsApi extends runtime.BaseAPI { } /** - * Check if a user is a member of an organization + * Creates request options for addOrganizationMemberAttributes without sending the request */ - async checkOrganizationMembershipRaw(requestParameters: CheckOrganizationMembershipRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async addOrganizationMemberAttributesRequestOpts(requestParameters: AddOrganizationMemberAttributesRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling addOrganizationMemberAttributes().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling addOrganizationMemberAttributes().' + ); + } + + if (requestParameters['userId'] == null) { + throw new runtime.RequiredError( + 'userId', + 'Required parameter "userId" was null or undefined when calling addOrganizationMemberAttributes().' + ); + } + + if (requestParameters['organizationMemberAttributeRepresentation'] == null) { + throw new runtime.RequiredError( + 'organizationMemberAttributeRepresentation', + 'Required parameter "organizationMemberAttributeRepresentation" was null or undefined when calling addOrganizationMemberAttributes().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/members/{userId}/attributes`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + + return { + path: urlPath, + method: 'PUT', + headers: headerParameters, + query: queryParameters, + body: OrganizationMemberAttributeRepresentationToJSON(requestParameters['organizationMemberAttributeRepresentation']), + }; + } + + /** + * Add or update attributes for a specific member of an organization + * Add/update organization member attributes + */ + async addOrganizationMemberAttributesRaw(requestParameters: AddOrganizationMemberAttributesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; }>> { + const requestOptions = await this.addOrganizationMemberAttributesRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Add or update attributes for a specific member of an organization + * Add/update organization member attributes + */ + async addOrganizationMemberAttributes(requestParameters: AddOrganizationMemberAttributesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{ [key: string]: Array; }> { + const response = await this.addOrganizationMemberAttributesRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for checkOrganizationMembership without sending the request + */ + async checkOrganizationMembershipRequestOpts(requestParameters: CheckOrganizationMembershipRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -151,12 +342,26 @@ export class OrganizationMembershipsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/members/{userId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"userId"}}`, encodeURIComponent(String(requestParameters['userId']))), + + let urlPath = `/{realm}/orgs/{orgId}/members/{userId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Check if a user is a member of an organization + */ + async checkOrganizationMembershipRaw(requestParameters: CheckOrganizationMembershipRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.checkOrganizationMembershipRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -169,10 +374,80 @@ export class OrganizationMembershipsApi extends runtime.BaseAPI { } /** - * Get a paginated list of users who are a member of the specified organization. - * Get organization memberships + * Creates request options for getOrganizationMemberAttributes without sending the request + */ + async getOrganizationMemberAttributesRequestOpts(requestParameters: GetOrganizationMemberAttributesRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getOrganizationMemberAttributes().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling getOrganizationMemberAttributes().' + ); + } + + if (requestParameters['userId'] == null) { + throw new runtime.RequiredError( + 'userId', + 'Required parameter "userId" was null or undefined when calling getOrganizationMemberAttributes().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/members/{userId}/attributes`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get attributes for a specific member of an organization + * Get organization member attributes */ - async getOrganizationMembershipsRaw(requestParameters: GetOrganizationMembershipsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + async getOrganizationMemberAttributesRaw(requestParameters: GetOrganizationMemberAttributesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise; }>> { + const requestOptions = await this.getOrganizationMemberAttributesRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response); + } + + /** + * Get attributes for a specific member of an organization + * Get organization member attributes + */ + async getOrganizationMemberAttributes(requestParameters: GetOrganizationMemberAttributesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise<{ [key: string]: Array; }> { + const response = await this.getOrganizationMemberAttributesRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getOrganizationMemberships without sending the request + */ + async getOrganizationMembershipsRequestOpts(requestParameters: GetOrganizationMembershipsRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -201,6 +476,14 @@ export class OrganizationMembershipsApi extends runtime.BaseAPI { queryParameters['max'] = requestParameters['max']; } + if (requestParameters['excludeAdminAccounts'] != null) { + queryParameters['excludeAdminAccounts'] = requestParameters['excludeAdminAccounts']; + } + + if (requestParameters['includeOrgs'] != null) { + queryParameters['includeOrgs'] = requestParameters['includeOrgs']; + } + const headerParameters: runtime.HTTPHeaders = {}; if (this.configuration && this.configuration.accessToken) { @@ -211,30 +494,43 @@ export class OrganizationMembershipsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/members`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/orgs/{orgId}/members`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } - return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(UserRepresentationFromJSON)); + /** + * Get a paginated list of users who are a member of the specified organization. + * Get organization memberships + */ + async getOrganizationMembershipsRaw(requestParameters: GetOrganizationMembershipsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getOrganizationMembershipsRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(UserWithOrgsBriefRepresentationFromJSON)); } /** * Get a paginated list of users who are a member of the specified organization. * Get organization memberships */ - async getOrganizationMemberships(requestParameters: GetOrganizationMembershipsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async getOrganizationMemberships(requestParameters: GetOrganizationMembershipsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { const response = await this.getOrganizationMembershipsRaw(requestParameters, initOverrides); return await response.value(); } /** - * Get total number of members of a given organization - * Get organization members count + * Creates request options for getOrganizationMembershipsCount without sending the request */ - async getOrganizationMembershipsCountRaw(requestParameters: GetOrganizationMembershipsCountRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async getOrganizationMembershipsCountRequestOpts(requestParameters: GetOrganizationMembershipsCountRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -251,6 +547,10 @@ export class OrganizationMembershipsApi extends runtime.BaseAPI { const queryParameters: any = {}; + if (requestParameters['excludeAdminAccounts'] != null) { + queryParameters['excludeAdminAccounts'] = requestParameters['excludeAdminAccounts']; + } + const headerParameters: runtime.HTTPHeaders = {}; if (this.configuration && this.configuration.accessToken) { @@ -261,12 +561,26 @@ export class OrganizationMembershipsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/members/count`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/orgs/{orgId}/members/count`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get total number of members of a given organization + * Get organization members count + */ + async getOrganizationMembershipsCountRaw(requestParameters: GetOrganizationMembershipsCountRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getOrganizationMembershipsCountRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); if (this.isJsonMime(response.headers.get('content-type'))) { return new runtime.JSONApiResponse(response); @@ -285,10 +599,9 @@ export class OrganizationMembershipsApi extends runtime.BaseAPI { } /** - * Remove the specified user from the specified organization as a member - * Remove an organization member + * Creates request options for removeOrganizationMember without sending the request */ - async removeOrganizationMemberRaw(requestParameters: RemoveOrganizationMemberRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async removeOrganizationMemberRequestOpts(requestParameters: RemoveOrganizationMemberRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -322,12 +635,27 @@ export class OrganizationMembershipsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/members/{userId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"userId"}}`, encodeURIComponent(String(requestParameters['userId']))), + + let urlPath = `/{realm}/orgs/{orgId}/members/{userId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + + return { + path: urlPath, method: 'DELETE', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Remove the specified user from the specified organization as a member + * Remove an organization member + */ + async removeOrganizationMemberRaw(requestParameters: RemoveOrganizationMemberRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.removeOrganizationMemberRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationRolesApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationRolesApi.ts index 7e49a99..1d95176 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationRolesApi.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationRolesApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -12,73 +12,197 @@ * Do not edit the class manually. */ - import * as runtime from '../runtime'; -import type { - OrganizationRoleRepresentation, - UserRepresentation, -} from '../models/index'; import { + type BulkResponseItem, + BulkResponseItemFromJSON, + BulkResponseItemToJSON, +} from '../models/BulkResponseItem'; +import { + type OrganizationRoleRepresentation, OrganizationRoleRepresentationFromJSON, OrganizationRoleRepresentationToJSON, +} from '../models/OrganizationRoleRepresentation'; +import { + type UserRepresentation, UserRepresentationFromJSON, UserRepresentationToJSON, -} from '../models/index'; +} from '../models/UserRepresentation'; export interface CheckUserOrganizationRoleRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * organization role name + */ name: string; + /** + * user id + */ userId: string; } export interface CreateOrganizationRoleRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ organizationRoleRepresentation: OrganizationRoleRepresentation; } +export interface CreateOrganizationRolesRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * + */ + organizationRoleRepresentation: Array; +} + export interface DeleteOrganizationRoleRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * organization role name + */ name: string; } +export interface DeleteOrganizationRolesRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * + */ + organizationRoleRepresentation: Array; +} + export interface GetOrganizationRoleRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * organization role name + */ name: string; } export interface GetOrganizationRolesRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; } export interface GetUserOrganizationRolesRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * organization role name + */ name: string; } export interface GrantUserOrganizationRoleRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * organization role name + */ name: string; + /** + * user id + */ userId: string; } export interface RevokeUserOrganizationRoleRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * organization role name + */ name: string; + /** + * user id + */ userId: string; } export interface UpdateOrganizationRoleRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * organization role name + */ name: string; + /** + * + */ organizationRoleRepresentation: OrganizationRoleRepresentation; } @@ -88,9 +212,9 @@ export interface UpdateOrganizationRoleRequest { export class OrganizationRolesApi extends runtime.BaseAPI { /** - * Check if a user has an organization role + * Creates request options for checkUserOrganizationRole without sending the request */ - async checkUserOrganizationRoleRaw(requestParameters: CheckUserOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async checkUserOrganizationRoleRequestOpts(requestParameters: CheckUserOrganizationRoleRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -131,12 +255,27 @@ export class OrganizationRolesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/roles/{name}/users/{userId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"name"}}`, encodeURIComponent(String(requestParameters['name']))).replace(`{${"userId"}}`, encodeURIComponent(String(requestParameters['userId']))), + + let urlPath = `/{realm}/orgs/{orgId}/roles/{name}/users/{userId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{name}', encodeURIComponent(String(requestParameters['name']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Check if a user has an organization role + */ + async checkUserOrganizationRoleRaw(requestParameters: CheckUserOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.checkUserOrganizationRoleRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -149,9 +288,9 @@ export class OrganizationRolesApi extends runtime.BaseAPI { } /** - * Create a new role for this organization + * Creates request options for createOrganizationRole without sending the request */ - async createOrganizationRoleRaw(requestParameters: CreateOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async createOrganizationRoleRequestOpts(requestParameters: CreateOrganizationRoleRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -187,13 +326,26 @@ export class OrganizationRolesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/roles`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/orgs/{orgId}/roles`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'POST', headers: headerParameters, query: queryParameters, body: OrganizationRoleRepresentationToJSON(requestParameters['organizationRoleRepresentation']), - }, initOverrides); + }; + } + + /** + * Create a new role for this organization + */ + async createOrganizationRoleRaw(requestParameters: CreateOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.createOrganizationRoleRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -206,9 +358,80 @@ export class OrganizationRolesApi extends runtime.BaseAPI { } /** - * Delete this organization role + * Creates request options for createOrganizationRoles without sending the request */ - async deleteOrganizationRoleRaw(requestParameters: DeleteOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async createOrganizationRolesRequestOpts(requestParameters: CreateOrganizationRolesRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling createOrganizationRoles().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling createOrganizationRoles().' + ); + } + + if (requestParameters['organizationRoleRepresentation'] == null) { + throw new runtime.RequiredError( + 'organizationRoleRepresentation', + 'Required parameter "organizationRoleRepresentation" was null or undefined when calling createOrganizationRoles().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/roles`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'PUT', + headers: headerParameters, + query: queryParameters, + body: requestParameters['organizationRoleRepresentation']!.map(OrganizationRoleRepresentationToJSON), + }; + } + + /** + * Create new roles for this organization + */ + async createOrganizationRolesRaw(requestParameters: CreateOrganizationRolesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.createOrganizationRolesRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(BulkResponseItemFromJSON)); + } + + /** + * Create new roles for this organization + */ + async createOrganizationRoles(requestParameters: CreateOrganizationRolesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const response = await this.createOrganizationRolesRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for deleteOrganizationRole without sending the request + */ + async deleteOrganizationRoleRequestOpts(requestParameters: DeleteOrganizationRoleRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -242,12 +465,26 @@ export class OrganizationRolesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/roles/{name}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"name"}}`, encodeURIComponent(String(requestParameters['name']))), + + let urlPath = `/{realm}/orgs/{orgId}/roles/{name}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{name}', encodeURIComponent(String(requestParameters['name']))); + + return { + path: urlPath, method: 'DELETE', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Delete this organization role + */ + async deleteOrganizationRoleRaw(requestParameters: DeleteOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.deleteOrganizationRoleRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -260,9 +497,80 @@ export class OrganizationRolesApi extends runtime.BaseAPI { } /** - * Get role for this organization by name + * Creates request options for deleteOrganizationRoles without sending the request */ - async getOrganizationRoleRaw(requestParameters: GetOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async deleteOrganizationRolesRequestOpts(requestParameters: DeleteOrganizationRolesRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling deleteOrganizationRoles().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling deleteOrganizationRoles().' + ); + } + + if (requestParameters['organizationRoleRepresentation'] == null) { + throw new runtime.RequiredError( + 'organizationRoleRepresentation', + 'Required parameter "organizationRoleRepresentation" was null or undefined when calling deleteOrganizationRoles().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/roles`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'PATCH', + headers: headerParameters, + query: queryParameters, + body: requestParameters['organizationRoleRepresentation']!.map(OrganizationRoleRepresentationToJSON), + }; + } + + /** + * Delete this organization roles + */ + async deleteOrganizationRolesRaw(requestParameters: DeleteOrganizationRolesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.deleteOrganizationRolesRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(BulkResponseItemFromJSON)); + } + + /** + * Delete this organization roles + */ + async deleteOrganizationRoles(requestParameters: DeleteOrganizationRolesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const response = await this.deleteOrganizationRolesRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getOrganizationRole without sending the request + */ + async getOrganizationRoleRequestOpts(requestParameters: GetOrganizationRoleRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -296,12 +604,26 @@ export class OrganizationRolesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/roles/{name}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"name"}}`, encodeURIComponent(String(requestParameters['name']))), + + let urlPath = `/{realm}/orgs/{orgId}/roles/{name}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{name}', encodeURIComponent(String(requestParameters['name']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get role for this organization by name + */ + async getOrganizationRoleRaw(requestParameters: GetOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getOrganizationRoleRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => OrganizationRoleRepresentationFromJSON(jsonValue)); } @@ -315,9 +637,9 @@ export class OrganizationRolesApi extends runtime.BaseAPI { } /** - * Get roles for this organization + * Creates request options for getOrganizationRoles without sending the request */ - async getOrganizationRolesRaw(requestParameters: GetOrganizationRolesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + async getOrganizationRolesRequestOpts(requestParameters: GetOrganizationRolesRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -344,12 +666,25 @@ export class OrganizationRolesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/roles`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/orgs/{orgId}/roles`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get roles for this organization + */ + async getOrganizationRolesRaw(requestParameters: GetOrganizationRolesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getOrganizationRolesRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(OrganizationRoleRepresentationFromJSON)); } @@ -363,9 +698,9 @@ export class OrganizationRolesApi extends runtime.BaseAPI { } /** - * Get users with this organization role + * Creates request options for getUserOrganizationRoles without sending the request */ - async getUserOrganizationRolesRaw(requestParameters: GetUserOrganizationRolesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + async getUserOrganizationRolesRequestOpts(requestParameters: GetUserOrganizationRolesRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -399,12 +734,26 @@ export class OrganizationRolesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/roles/{name}/users`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"name"}}`, encodeURIComponent(String(requestParameters['name']))), + + let urlPath = `/{realm}/orgs/{orgId}/roles/{name}/users`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{name}', encodeURIComponent(String(requestParameters['name']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get users with this organization role + */ + async getUserOrganizationRolesRaw(requestParameters: GetUserOrganizationRolesRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getUserOrganizationRolesRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(UserRepresentationFromJSON)); } @@ -418,10 +767,9 @@ export class OrganizationRolesApi extends runtime.BaseAPI { } /** - * Grant the specified user to the specified organization role - * Grant a user an organization role + * Creates request options for grantUserOrganizationRole without sending the request */ - async grantUserOrganizationRoleRaw(requestParameters: GrantUserOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async grantUserOrganizationRoleRequestOpts(requestParameters: GrantUserOrganizationRoleRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -462,12 +810,28 @@ export class OrganizationRolesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/roles/{name}/users/{userId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"name"}}`, encodeURIComponent(String(requestParameters['name']))).replace(`{${"userId"}}`, encodeURIComponent(String(requestParameters['userId']))), + + let urlPath = `/{realm}/orgs/{orgId}/roles/{name}/users/{userId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{name}', encodeURIComponent(String(requestParameters['name']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + + return { + path: urlPath, method: 'PUT', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Grant the specified user to the specified organization role + * Grant a user an organization role + */ + async grantUserOrganizationRoleRaw(requestParameters: GrantUserOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.grantUserOrganizationRoleRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -481,10 +845,9 @@ export class OrganizationRolesApi extends runtime.BaseAPI { } /** - * Revoke the specified organization role from the specified user - * Revoke an organization role from a user + * Creates request options for revokeUserOrganizationRole without sending the request */ - async revokeUserOrganizationRoleRaw(requestParameters: RevokeUserOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async revokeUserOrganizationRoleRequestOpts(requestParameters: RevokeUserOrganizationRoleRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -525,12 +888,28 @@ export class OrganizationRolesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/roles/{name}/users/{userId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"name"}}`, encodeURIComponent(String(requestParameters['name']))).replace(`{${"userId"}}`, encodeURIComponent(String(requestParameters['userId']))), + + let urlPath = `/{realm}/orgs/{orgId}/roles/{name}/users/{userId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{name}', encodeURIComponent(String(requestParameters['name']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + + return { + path: urlPath, method: 'DELETE', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Revoke the specified organization role from the specified user + * Revoke an organization role from a user + */ + async revokeUserOrganizationRoleRaw(requestParameters: RevokeUserOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.revokeUserOrganizationRoleRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -544,9 +923,9 @@ export class OrganizationRolesApi extends runtime.BaseAPI { } /** - * Update role for this organization + * Creates request options for updateOrganizationRole without sending the request */ - async updateOrganizationRoleRaw(requestParameters: UpdateOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async updateOrganizationRoleRequestOpts(requestParameters: UpdateOrganizationRoleRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -589,13 +968,27 @@ export class OrganizationRolesApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/roles/{name}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))).replace(`{${"name"}}`, encodeURIComponent(String(requestParameters['name']))), + + let urlPath = `/{realm}/orgs/{orgId}/roles/{name}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + urlPath = urlPath.replace('{name}', encodeURIComponent(String(requestParameters['name']))); + + return { + path: urlPath, method: 'PUT', headers: headerParameters, query: queryParameters, body: OrganizationRoleRepresentationToJSON(requestParameters['organizationRoleRepresentation']), - }, initOverrides); + }; + } + + /** + * Update role for this organization + */ + async updateOrganizationRoleRaw(requestParameters: UpdateOrganizationRoleRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.updateOrganizationRoleRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationSCIMApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationSCIMApi.ts new file mode 100644 index 0000000..ebe7927 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationSCIMApi.ts @@ -0,0 +1,350 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import * as runtime from '../runtime'; +import { + type OrganizationScimRepresentation, + OrganizationScimRepresentationFromJSON, + OrganizationScimRepresentationToJSON, +} from '../models/OrganizationScimRepresentation'; + +export interface CreateOrganizationScimConfigRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * + */ + organizationScimRepresentation: OrganizationScimRepresentation; +} + +export interface DeleteOrganizationScimConfigRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; +} + +export interface GetOrganizationScimConfigRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; +} + +export interface UpdateOrganizationScimConfigRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * organization id + */ + orgId: string; + /** + * + */ + organizationScimRepresentation: OrganizationScimRepresentation; +} + +/** + * + */ +export class OrganizationSCIMApi extends runtime.BaseAPI { + + /** + * Creates request options for createOrganizationScimConfig without sending the request + */ + async createOrganizationScimConfigRequestOpts(requestParameters: CreateOrganizationScimConfigRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling createOrganizationScimConfig().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling createOrganizationScimConfig().' + ); + } + + if (requestParameters['organizationScimRepresentation'] == null) { + throw new runtime.RequiredError( + 'organizationScimRepresentation', + 'Required parameter "organizationScimRepresentation" was null or undefined when calling createOrganizationScimConfig().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/scim`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: OrganizationScimRepresentationToJSON(requestParameters['organizationScimRepresentation']), + }; + } + + /** + * Creates the SCIM 2.0 service-provider configuration for the organization. Requires `manage-organizations` or `manage-identity-providers` on the organization. Returns 404 if the realm-level SCIM flag is off, and 409 if a configuration already exists for the organization. Cleartext secrets and basic passwords submitted here are hashed with Argon2id before persistence. + * Create the SCIM configuration for an organization + */ + async createOrganizationScimConfigRaw(requestParameters: CreateOrganizationScimConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.createOrganizationScimConfigRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => OrganizationScimRepresentationFromJSON(jsonValue)); + } + + /** + * Creates the SCIM 2.0 service-provider configuration for the organization. Requires `manage-organizations` or `manage-identity-providers` on the organization. Returns 404 if the realm-level SCIM flag is off, and 409 if a configuration already exists for the organization. Cleartext secrets and basic passwords submitted here are hashed with Argon2id before persistence. + * Create the SCIM configuration for an organization + */ + async createOrganizationScimConfig(requestParameters: CreateOrganizationScimConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.createOrganizationScimConfigRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for deleteOrganizationScimConfig without sending the request + */ + async deleteOrganizationScimConfigRequestOpts(requestParameters: DeleteOrganizationScimConfigRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling deleteOrganizationScimConfig().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling deleteOrganizationScimConfig().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/scim`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'DELETE', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Removes the SCIM 2.0 service-provider configuration for the organization. Requires `manage-organizations` or `manage-identity-providers` on the organization. + * Delete the SCIM configuration for an organization + */ + async deleteOrganizationScimConfigRaw(requestParameters: DeleteOrganizationScimConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.deleteOrganizationScimConfigRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Removes the SCIM 2.0 service-provider configuration for the organization. Requires `manage-organizations` or `manage-identity-providers` on the organization. + * Delete the SCIM configuration for an organization + */ + async deleteOrganizationScimConfig(requestParameters: DeleteOrganizationScimConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.deleteOrganizationScimConfigRaw(requestParameters, initOverrides); + } + + /** + * Creates request options for getOrganizationScimConfig without sending the request + */ + async getOrganizationScimConfigRequestOpts(requestParameters: GetOrganizationScimConfigRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getOrganizationScimConfig().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling getOrganizationScimConfig().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/scim`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Returns the SCIM 2.0 service-provider configuration for the organization. Requires `view-organizations` or `view-identity-providers` on the organization. Returns 404 if the realm-level SCIM flag (`scimEnabled` in the orgs config) is off, or if no configuration exists for the organization yet. + * Get the SCIM configuration for an organization + */ + async getOrganizationScimConfigRaw(requestParameters: GetOrganizationScimConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getOrganizationScimConfigRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => OrganizationScimRepresentationFromJSON(jsonValue)); + } + + /** + * Returns the SCIM 2.0 service-provider configuration for the organization. Requires `view-organizations` or `view-identity-providers` on the organization. Returns 404 if the realm-level SCIM flag (`scimEnabled` in the orgs config) is off, or if no configuration exists for the organization yet. + * Get the SCIM configuration for an organization + */ + async getOrganizationScimConfig(requestParameters: GetOrganizationScimConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getOrganizationScimConfigRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for updateOrganizationScimConfig without sending the request + */ + async updateOrganizationScimConfigRequestOpts(requestParameters: UpdateOrganizationScimConfigRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling updateOrganizationScimConfig().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling updateOrganizationScimConfig().' + ); + } + + if (requestParameters['organizationScimRepresentation'] == null) { + throw new runtime.RequiredError( + 'organizationScimRepresentation', + 'Required parameter "organizationScimRepresentation" was null or undefined when calling updateOrganizationScimConfig().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/{orgId}/scim`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'PUT', + headers: headerParameters, + query: queryParameters, + body: OrganizationScimRepresentationToJSON(requestParameters['organizationScimRepresentation']), + }; + } + + /** + * Updates the SCIM 2.0 service-provider configuration for the organization. Requires `manage-organizations` or `manage-identity-providers` on the organization. Omit secret/password fields on `auth` to preserve the existing stored credential; supply a new value to rotate. + * Update the SCIM configuration for an organization + */ + async updateOrganizationScimConfigRaw(requestParameters: UpdateOrganizationScimConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.updateOrganizationScimConfigRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => OrganizationScimRepresentationFromJSON(jsonValue)); + } + + /** + * Updates the SCIM 2.0 service-provider configuration for the organization. Requires `manage-organizations` or `manage-identity-providers` on the organization. Omit secret/password fields on `auth` to preserve the existing stored credential; supply a new value to rotate. + * Update the SCIM configuration for an organization + */ + async updateOrganizationScimConfig(requestParameters: UpdateOrganizationScimConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.updateOrganizationScimConfigRaw(requestParameters, initOverrides); + return await response.value(); + } + +} diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationsApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationsApi.ts index 193d0ab..42047ba 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationsApi.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/OrganizationsApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -12,75 +12,329 @@ * Do not edit the class manually. */ - import * as runtime from '../runtime'; -import type { - MyOrganizationRepresentation, - OrganizationRepresentation, - PortalLinkRepresentation, -} from '../models/index'; import { + type ImportOrganizationsForm, + ImportOrganizationsFormFromJSON, + ImportOrganizationsFormToJSON, +} from '../models/ImportOrganizationsForm'; +import { + type InvitationRepresentation, + InvitationRepresentationFromJSON, + InvitationRepresentationToJSON, +} from '../models/InvitationRepresentation'; +import { + type MyOrganizationRepresentation, MyOrganizationRepresentationFromJSON, MyOrganizationRepresentationToJSON, +} from '../models/MyOrganizationRepresentation'; +import { + type OrganizationConfigRepresentation, + OrganizationConfigRepresentationFromJSON, + OrganizationConfigRepresentationToJSON, +} from '../models/OrganizationConfigRepresentation'; +import { + type OrganizationRepresentation, OrganizationRepresentationFromJSON, OrganizationRepresentationToJSON, +} from '../models/OrganizationRepresentation'; +import { + type OrganizationsExportRepresentation, + OrganizationsExportRepresentationFromJSON, + OrganizationsExportRepresentationToJSON, +} from '../models/OrganizationsExportRepresentation'; +import { + type OrganizationsImportRepresentation, + OrganizationsImportRepresentationFromJSON, + OrganizationsImportRepresentationToJSON, +} from '../models/OrganizationsImportRepresentation'; +import { + type OrganizationsImportResultRepresentation, + OrganizationsImportResultRepresentationFromJSON, + OrganizationsImportResultRepresentationToJSON, +} from '../models/OrganizationsImportResultRepresentation'; +import { + type PortalLinkRepresentation, PortalLinkRepresentationFromJSON, PortalLinkRepresentationToJSON, -} from '../models/index'; +} from '../models/PortalLinkRepresentation'; + +export interface AcceptInvitationRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * invitation UUID + */ + invitationId: string; +} export interface CreateOrganizationRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * + */ organizationRepresentation: OrganizationRepresentation; } export interface CreatePortalLinkRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ userId?: string; } export interface DeleteOrganizationRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; } +export interface ExportOrganizationsRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * Include organization members in the export + */ + includeMembers?: boolean; + /** + * Include organization roles in the export + */ + includeRoles?: boolean; + /** + * Include identity providers in the export + */ + includeIdps?: boolean; + /** + * Specific organization IDs to export (if not provided, exports all) + */ + orgIds?: Array; +} + export interface GetMeRequest { + /** + * realm name (not id!) + */ realm: string; } export interface GetOrganizationByIdRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; } +export interface GetOrganizationConfigRequest { + /** + * realm name (not id!) + */ + realm: string; +} + export interface GetOrganizationsRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * search by name + */ search?: string; + /** + * + */ first?: number; + /** + * + */ max?: number; + /** + * search by attributes using the format (space separated) `k1:v1 k2:v2` + */ q?: string; + /** + * search parameter exact match + */ + exact?: string; } export interface GetOrganizationsCountRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * + */ search?: string; + /** + * search by attributes using the format (space separated) `k1:v1 k2:v2` + */ + q?: string; + /** + * exact search + */ + exact?: string; +} + +export interface ImportOrganizationsRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * + */ + organizationsImportRepresentation: OrganizationsImportRepresentation; + /** + * Skip organizations that already exist instead of updating them + */ + skipExisting?: boolean; + /** + * Import organization members (requires existing users in realm) + */ + importMembers?: boolean; +} + +export interface InvitationsRequest { + /** + * realm name (not id!) + */ + realm: string; +} + +export interface RejectInvitationRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * invitation UUID + */ + invitationId: string; } export interface UpdateOrganizationRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * organization id + */ orgId: string; + /** + * + */ organizationRepresentation: OrganizationRepresentation; } +export interface UpdateOrganizationConfigRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * + */ + organizationConfigRepresentation: OrganizationConfigRepresentation; +} + /** * */ export class OrganizationsApi extends runtime.BaseAPI { /** - * Create a new organization + * Creates request options for acceptInvitation without sending the request */ - async createOrganizationRaw(requestParameters: CreateOrganizationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async acceptInvitationRequestOpts(requestParameters: AcceptInvitationRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling acceptInvitation().' + ); + } + + if (requestParameters['invitationId'] == null) { + throw new runtime.RequiredError( + 'invitationId', + 'Required parameter "invitationId" was null or undefined when calling acceptInvitation().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/me/invitations/{invitationId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{invitationId}', encodeURIComponent(String(requestParameters['invitationId']))); + + return { + path: urlPath, + method: 'POST', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Accept invitation for authenticated user. + * Accept invitation for authenticated user + */ + async acceptInvitationRaw(requestParameters: AcceptInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.acceptInvitationRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Accept invitation for authenticated user. + * Accept invitation for authenticated user + */ + async acceptInvitation(requestParameters: AcceptInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.acceptInvitationRaw(requestParameters, initOverrides); + } + + /** + * Creates request options for createOrganization without sending the request + */ + async createOrganizationRequestOpts(requestParameters: CreateOrganizationRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -109,13 +363,25 @@ export class OrganizationsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))), + + let urlPath = `/{realm}/orgs`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, method: 'POST', headers: headerParameters, query: queryParameters, body: OrganizationRepresentationToJSON(requestParameters['organizationRepresentation']), - }, initOverrides); + }; + } + + /** + * Create a new organization + */ + async createOrganizationRaw(requestParameters: CreateOrganizationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.createOrganizationRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -128,10 +394,9 @@ export class OrganizationsApi extends runtime.BaseAPI { } /** - * Create a link for this organizations admin portal. This link encodes an action token on behalf of the organization\'s default admin user, or the user that is optionally specified in this request. The user specified must be a member of this organization, and have full organization admin roles. - * Create a link for the organization\'s admin portal + * Creates request options for createPortalLink without sending the request */ - async createPortalLinkRaw(requestParameters: CreatePortalLinkRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async createPortalLinkRequestOpts(requestParameters: CreatePortalLinkRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -176,20 +441,34 @@ export class OrganizationsApi extends runtime.BaseAPI { formParams.append('userId', requestParameters['userId'] as any); } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}/portal-link`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/orgs/{orgId}/portal-link`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'POST', headers: headerParameters, query: queryParameters, body: formParams, - }, initOverrides); + }; + } + + /** + * Create a link for this organization\'s IdP Wizard. This link encodes an action token on behalf of the organization\'s default admin user, or the user that is optionally specified in this request. The user specified must be a member of this organization, and have full organization admin roles. + * Create a link for the organization\'s IdP Wizard + */ + async createPortalLinkRaw(requestParameters: CreatePortalLinkRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.createPortalLinkRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => PortalLinkRepresentationFromJSON(jsonValue)); } /** - * Create a link for this organizations admin portal. This link encodes an action token on behalf of the organization\'s default admin user, or the user that is optionally specified in this request. The user specified must be a member of this organization, and have full organization admin roles. - * Create a link for the organization\'s admin portal + * Create a link for this organization\'s IdP Wizard. This link encodes an action token on behalf of the organization\'s default admin user, or the user that is optionally specified in this request. The user specified must be a member of this organization, and have full organization admin roles. + * Create a link for the organization\'s IdP Wizard */ async createPortalLink(requestParameters: CreatePortalLinkRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { const response = await this.createPortalLinkRaw(requestParameters, initOverrides); @@ -197,9 +476,9 @@ export class OrganizationsApi extends runtime.BaseAPI { } /** - * Delete the organization + * Creates request options for deleteOrganization without sending the request */ - async deleteOrganizationRaw(requestParameters: DeleteOrganizationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async deleteOrganizationRequestOpts(requestParameters: DeleteOrganizationRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -226,12 +505,25 @@ export class OrganizationsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/orgs/{orgId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'DELETE', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Delete the organization + */ + async deleteOrganizationRaw(requestParameters: DeleteOrganizationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.deleteOrganizationRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -244,10 +536,80 @@ export class OrganizationsApi extends runtime.BaseAPI { } /** - * Get a list of all organizations that the user is a member and their roles in those organizations. Similar idea to /userinfo in OIDC. - * Get orgs and roles for authenticated user + * Creates request options for exportOrganizations without sending the request */ - async getMeRaw(requestParameters: GetMeRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async exportOrganizationsRequestOpts(requestParameters: ExportOrganizationsRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling exportOrganizations().' + ); + } + + const queryParameters: any = {}; + + if (requestParameters['includeMembers'] != null) { + queryParameters['includeMembers'] = requestParameters['includeMembers']; + } + + if (requestParameters['includeRoles'] != null) { + queryParameters['includeRoles'] = requestParameters['includeRoles']; + } + + if (requestParameters['includeIdps'] != null) { + queryParameters['includeIdps'] = requestParameters['includeIdps']; + } + + if (requestParameters['orgIds'] != null) { + queryParameters['orgIds'] = requestParameters['orgIds']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/export`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Export all organizations and their configurations from this realm + * Export organizations + */ + async exportOrganizationsRaw(requestParameters: ExportOrganizationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.exportOrganizationsRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => OrganizationsExportRepresentationFromJSON(jsonValue)); + } + + /** + * Export all organizations and their configurations from this realm + * Export organizations + */ + async exportOrganizations(requestParameters: ExportOrganizationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.exportOrganizationsRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getMe without sending the request + */ + async getMeRequestOpts(requestParameters: GetMeRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -267,12 +629,25 @@ export class OrganizationsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/me`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))), + + let urlPath = `/{realm}/orgs/me`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get a list of all organizations that the user is a member and their roles in those organizations. Similar idea to /userinfo in OIDC. + * Get orgs and roles for authenticated user + */ + async getMeRaw(requestParameters: GetMeRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getMeRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => runtime.mapValues(jsonValue, MyOrganizationRepresentationFromJSON)); } @@ -287,9 +662,9 @@ export class OrganizationsApi extends runtime.BaseAPI { } /** - * Get organization by id + * Creates request options for getOrganizationById without sending the request */ - async getOrganizationByIdRaw(requestParameters: GetOrganizationByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async getOrganizationByIdRequestOpts(requestParameters: GetOrganizationByIdRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -316,12 +691,25 @@ export class OrganizationsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/orgs/{orgId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get organization by id + */ + async getOrganizationByIdRaw(requestParameters: GetOrganizationByIdRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getOrganizationByIdRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => OrganizationRepresentationFromJSON(jsonValue)); } @@ -335,10 +723,64 @@ export class OrganizationsApi extends runtime.BaseAPI { } /** - * Get a paginated list of organizations using optional search query parameters. - * Get organizations + * Creates request options for getOrganizationConfig without sending the request */ - async getOrganizationsRaw(requestParameters: GetOrganizationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + async getOrganizationConfigRequestOpts(requestParameters: GetOrganizationConfigRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getOrganizationConfig().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/config`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get the global organization configuration for this realm + * Get organization configuration + */ + async getOrganizationConfigRaw(requestParameters: GetOrganizationConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getOrganizationConfigRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => OrganizationConfigRepresentationFromJSON(jsonValue)); + } + + /** + * Get the global organization configuration for this realm + * Get organization configuration + */ + async getOrganizationConfig(requestParameters: GetOrganizationConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getOrganizationConfigRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for getOrganizations without sending the request + */ + async getOrganizationsRequestOpts(requestParameters: GetOrganizationsRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -364,6 +806,10 @@ export class OrganizationsApi extends runtime.BaseAPI { queryParameters['q'] = requestParameters['q']; } + if (requestParameters['exact'] != null) { + queryParameters['exact'] = requestParameters['exact']; + } + const headerParameters: runtime.HTTPHeaders = {}; if (this.configuration && this.configuration.accessToken) { @@ -374,12 +820,25 @@ export class OrganizationsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))), + + let urlPath = `/{realm}/orgs`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get a paginated list of organizations using optional search query parameters. + * Get organizations + */ + async getOrganizationsRaw(requestParameters: GetOrganizationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.getOrganizationsRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(OrganizationRepresentationFromJSON)); } @@ -394,10 +853,9 @@ export class OrganizationsApi extends runtime.BaseAPI { } /** - * Get a count of organizations using an optional search query. - * Get organizations count + * Creates request options for getOrganizationsCount without sending the request */ - async getOrganizationsCountRaw(requestParameters: GetOrganizationsCountRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async getOrganizationsCountRequestOpts(requestParameters: GetOrganizationsCountRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -411,6 +869,14 @@ export class OrganizationsApi extends runtime.BaseAPI { queryParameters['search'] = requestParameters['search']; } + if (requestParameters['q'] != null) { + queryParameters['q'] = requestParameters['q']; + } + + if (requestParameters['exact'] != null) { + queryParameters['exact'] = requestParameters['exact']; + } + const headerParameters: runtime.HTTPHeaders = {}; if (this.configuration && this.configuration.accessToken) { @@ -421,12 +887,25 @@ export class OrganizationsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/count`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))), + + let urlPath = `/{realm}/orgs/count`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * Get a count of organizations using an optional search query. + * Get organizations count + */ + async getOrganizationsCountRaw(requestParameters: GetOrganizationsCountRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getOrganizationsCountRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); if (this.isJsonMime(response.headers.get('content-type'))) { return new runtime.JSONApiResponse(response); @@ -445,9 +924,199 @@ export class OrganizationsApi extends runtime.BaseAPI { } /** - * Update this organization by id + * Creates request options for importOrganizations without sending the request */ - async updateOrganizationRaw(requestParameters: UpdateOrganizationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async importOrganizationsRequestOpts(requestParameters: ImportOrganizationsRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling importOrganizations().' + ); + } + + if (requestParameters['organizationsImportRepresentation'] == null) { + throw new runtime.RequiredError( + 'organizationsImportRepresentation', + 'Required parameter "organizationsImportRepresentation" was null or undefined when calling importOrganizations().' + ); + } + + const queryParameters: any = {}; + + if (requestParameters['skipExisting'] != null) { + queryParameters['skipExisting'] = requestParameters['skipExisting']; + } + + if (requestParameters['importMembers'] != null) { + queryParameters['importMembers'] = requestParameters['importMembers']; + } + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/import`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, + method: 'POST', + headers: headerParameters, + query: queryParameters, + body: OrganizationsImportRepresentationToJSON(requestParameters['organizationsImportRepresentation']), + }; + } + + /** + * Import organizations and their configurations into this realm + * Import organizations + */ + async importOrganizationsRaw(requestParameters: ImportOrganizationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.importOrganizationsRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => OrganizationsImportResultRepresentationFromJSON(jsonValue)); + } + + /** + * Import organizations and their configurations into this realm + * Import organizations + */ + async importOrganizations(requestParameters: ImportOrganizationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.importOrganizationsRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for invitations without sending the request + */ + async invitationsRequestOpts(requestParameters: InvitationsRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling invitations().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/me/invitations`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get a list of all invitations for the user. + * Get invitations for authenticated user + */ + async invitationsRaw(requestParameters: InvitationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.invitationsRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => InvitationRepresentationFromJSON(jsonValue)); + } + + /** + * Get a list of all invitations for the user. + * Get invitations for authenticated user + */ + async invitations(requestParameters: InvitationsRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.invitationsRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for rejectInvitation without sending the request + */ + async rejectInvitationRequestOpts(requestParameters: RejectInvitationRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling rejectInvitation().' + ); + } + + if (requestParameters['invitationId'] == null) { + throw new runtime.RequiredError( + 'invitationId', + 'Required parameter "invitationId" was null or undefined when calling rejectInvitation().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/me/invitations/{invitationId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{invitationId}', encodeURIComponent(String(requestParameters['invitationId']))); + + return { + path: urlPath, + method: 'DELETE', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Reject invitation for authenticated user. + * Reject invitation for authenticated user + */ + async rejectInvitationRaw(requestParameters: RejectInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.rejectInvitationRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Reject invitation for authenticated user. + * Reject invitation for authenticated user + */ + async rejectInvitation(requestParameters: RejectInvitationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.rejectInvitationRaw(requestParameters, initOverrides); + } + + /** + * Creates request options for updateOrganization without sending the request + */ + async updateOrganizationRequestOpts(requestParameters: UpdateOrganizationRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -483,13 +1152,26 @@ export class OrganizationsApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/orgs/{orgId}`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/orgs/{orgId}`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'PUT', headers: headerParameters, query: queryParameters, body: OrganizationRepresentationToJSON(requestParameters['organizationRepresentation']), - }, initOverrides); + }; + } + + /** + * Update this organization by id + */ + async updateOrganizationRaw(requestParameters: UpdateOrganizationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.updateOrganizationRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.VoidApiResponse(response); } @@ -501,4 +1183,68 @@ export class OrganizationsApi extends runtime.BaseAPI { await this.updateOrganizationRaw(requestParameters, initOverrides); } + /** + * Creates request options for updateOrganizationConfig without sending the request + */ + async updateOrganizationConfigRequestOpts(requestParameters: UpdateOrganizationConfigRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling updateOrganizationConfig().' + ); + } + + if (requestParameters['organizationConfigRepresentation'] == null) { + throw new runtime.RequiredError( + 'organizationConfigRepresentation', + 'Required parameter "organizationConfigRepresentation" was null or undefined when calling updateOrganizationConfig().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/orgs/config`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, + method: 'PUT', + headers: headerParameters, + query: queryParameters, + body: OrganizationConfigRepresentationToJSON(requestParameters['organizationConfigRepresentation']), + }; + } + + /** + * Update the global organization configuration for this realm + * Update organization configuration + */ + async updateOrganizationConfigRaw(requestParameters: UpdateOrganizationConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.updateOrganizationConfigRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.VoidApiResponse(response); + } + + /** + * Update the global organization configuration for this realm + * Update organization configuration + */ + async updateOrganizationConfig(requestParameters: UpdateOrganizationConfigRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + await this.updateOrganizationConfigRaw(requestParameters, initOverrides); + } + } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/UsersApi.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/UsersApi.ts index 867a913..42304c9 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/UsersApi.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/UsersApi.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -12,47 +12,145 @@ * Do not edit the class manually. */ - import * as runtime from '../runtime'; -import type { - MagicLinkRepresentation, - OrganizationRepresentation, - OrganizationRoleRepresentation, -} from '../models/index'; import { - MagicLinkRepresentationFromJSON, - MagicLinkRepresentationToJSON, + type AccessTokenResponse, + AccessTokenResponseFromJSON, + AccessTokenResponseToJSON, +} from '../models/AccessTokenResponse'; +import { + type BulkResponseItem, + BulkResponseItemFromJSON, + BulkResponseItemToJSON, +} from '../models/BulkResponseItem'; +import { + type MagicLinkRequest, + MagicLinkRequestFromJSON, + MagicLinkRequestToJSON, +} from '../models/MagicLinkRequest'; +import { + type MagicLinkResponse, + MagicLinkResponseFromJSON, + MagicLinkResponseToJSON, +} from '../models/MagicLinkResponse'; +import { + type OrganizationRepresentation, OrganizationRepresentationFromJSON, OrganizationRepresentationToJSON, +} from '../models/OrganizationRepresentation'; +import { + type OrganizationRoleRepresentation, OrganizationRoleRepresentationFromJSON, OrganizationRoleRepresentationToJSON, -} from '../models/index'; +} from '../models/OrganizationRoleRepresentation'; +import { + type SwitchOrganizationRepresentation, + SwitchOrganizationRepresentationFromJSON, + SwitchOrganizationRepresentationToJSON, +} from '../models/SwitchOrganizationRepresentation'; export interface CreateMagicLinkRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * + */ + magicLinkRequest: MagicLinkRequest; +} + +export interface GetActiveOrganizationRequest { + /** + * realm name (not id!) + */ realm: string; - magicLinkRepresentation: MagicLinkRepresentation; } export interface RealmUsersUserIdOrgsGetRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * user id + */ userId: string; } export interface RealmUsersUserIdOrgsOrgIdRolesGetRequest { + /** + * realm name (not id!) + */ realm: string; + /** + * user id + */ userId: string; + /** + * organization id + */ orgId: string; } +export interface RealmUsersUserIdOrgsOrgIdRolesPatchRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * user id + */ + userId: string; + /** + * organization id + */ + orgId: string; + /** + * + */ + organizationRoleRepresentation: Array; +} + +export interface RealmUsersUserIdOrgsOrgIdRolesPutRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * user id + */ + userId: string; + /** + * organization id + */ + orgId: string; + /** + * + */ + organizationRoleRepresentation: Array; +} + +export interface SwitchActiveOrganizationRequest { + /** + * realm name (not id!) + */ + realm: string; + /** + * + */ + switchOrganizationRepresentation: SwitchOrganizationRepresentation; +} + /** * */ export class UsersApi extends runtime.BaseAPI { /** - * Create a magic link to log in a user + * Creates request options for createMagicLink without sending the request */ - async createMagicLinkRaw(requestParameters: CreateMagicLinkRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + async createMagicLinkRequestOpts(requestParameters: CreateMagicLinkRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -60,10 +158,10 @@ export class UsersApi extends runtime.BaseAPI { ); } - if (requestParameters['magicLinkRepresentation'] == null) { + if (requestParameters['magicLinkRequest'] == null) { throw new runtime.RequiredError( - 'magicLinkRepresentation', - 'Required parameter "magicLinkRepresentation" was null or undefined when calling createMagicLink().' + 'magicLinkRequest', + 'Required parameter "magicLinkRequest" was null or undefined when calling createMagicLink().' ); } @@ -81,28 +179,103 @@ export class UsersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/magic-link`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))), + + let urlPath = `/{realm}/magic-link`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, method: 'POST', headers: headerParameters, query: queryParameters, - body: MagicLinkRepresentationToJSON(requestParameters['magicLinkRepresentation']), - }, initOverrides); + body: MagicLinkRequestToJSON(requestParameters['magicLinkRequest']), + }; + } + + /** + * Create a magic link to log in a user + */ + async createMagicLinkRaw(requestParameters: CreateMagicLinkRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.createMagicLinkRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); - return new runtime.VoidApiResponse(response); + return new runtime.JSONApiResponse(response, (jsonValue) => MagicLinkResponseFromJSON(jsonValue)); } /** * Create a magic link to log in a user */ - async createMagicLink(requestParameters: CreateMagicLinkRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { - await this.createMagicLinkRaw(requestParameters, initOverrides); + async createMagicLink(requestParameters: CreateMagicLinkRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.createMagicLinkRaw(requestParameters, initOverrides); + return await response.value(); } /** - * List organizations for the given user + * Creates request options for getActiveOrganization without sending the request */ - async realmUsersUserIdOrgsGetRaw(requestParameters: RealmUsersUserIdOrgsGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + async getActiveOrganizationRequestOpts(requestParameters: GetActiveOrganizationRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling getActiveOrganization().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/users/active-organization`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, + method: 'GET', + headers: headerParameters, + query: queryParameters, + }; + } + + /** + * Get the currently active organization for the authenticated user + * Get active organization for authenticated user + */ + async getActiveOrganizationRaw(requestParameters: GetActiveOrganizationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.getActiveOrganizationRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => OrganizationRepresentationFromJSON(jsonValue)); + } + + /** + * Get the currently active organization for the authenticated user + * Get active organization for authenticated user + */ + async getActiveOrganization(requestParameters: GetActiveOrganizationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.getActiveOrganizationRaw(requestParameters, initOverrides); + switch (response.raw.status) { + case 200: + return await response.value(); + case 204: + return null; + default: + return await response.value(); + } + } + + /** + * Creates request options for realmUsersUserIdOrgsGet without sending the request + */ + async realmUsersUserIdOrgsGetRequestOpts(requestParameters: RealmUsersUserIdOrgsGetRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -129,12 +302,25 @@ export class UsersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/users/{userId}/orgs`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"userId"}}`, encodeURIComponent(String(requestParameters['userId']))), + + let urlPath = `/{realm}/users/{userId}/orgs`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * List organizations for the given user + */ + async realmUsersUserIdOrgsGetRaw(requestParameters: RealmUsersUserIdOrgsGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.realmUsersUserIdOrgsGetRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(OrganizationRepresentationFromJSON)); } @@ -148,9 +334,9 @@ export class UsersApi extends runtime.BaseAPI { } /** - * List organization roles for the given user and org + * Creates request options for realmUsersUserIdOrgsOrgIdRolesGet without sending the request */ - async realmUsersUserIdOrgsOrgIdRolesGetRaw(requestParameters: RealmUsersUserIdOrgsOrgIdRolesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + async realmUsersUserIdOrgsOrgIdRolesGetRequestOpts(requestParameters: RealmUsersUserIdOrgsOrgIdRolesGetRequest): Promise { if (requestParameters['realm'] == null) { throw new runtime.RequiredError( 'realm', @@ -184,12 +370,26 @@ export class UsersApi extends runtime.BaseAPI { headerParameters["Authorization"] = `Bearer ${tokenString}`; } } - const response = await this.request({ - path: `/{realm}/users/{userId}/orgs/{orgId}/roles`.replace(`{${"realm"}}`, encodeURIComponent(String(requestParameters['realm']))).replace(`{${"userId"}}`, encodeURIComponent(String(requestParameters['userId']))).replace(`{${"orgId"}}`, encodeURIComponent(String(requestParameters['orgId']))), + + let urlPath = `/{realm}/users/{userId}/orgs/{orgId}/roles`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, method: 'GET', headers: headerParameters, query: queryParameters, - }, initOverrides); + }; + } + + /** + * List organization roles for the given user and org + */ + async realmUsersUserIdOrgsOrgIdRolesGetRaw(requestParameters: RealmUsersUserIdOrgsOrgIdRolesGetRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.realmUsersUserIdOrgsOrgIdRolesGetRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(OrganizationRoleRepresentationFromJSON)); } @@ -202,4 +402,227 @@ export class UsersApi extends runtime.BaseAPI { return await response.value(); } + /** + * Creates request options for realmUsersUserIdOrgsOrgIdRolesPatch without sending the request + */ + async realmUsersUserIdOrgsOrgIdRolesPatchRequestOpts(requestParameters: RealmUsersUserIdOrgsOrgIdRolesPatchRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling realmUsersUserIdOrgsOrgIdRolesPatch().' + ); + } + + if (requestParameters['userId'] == null) { + throw new runtime.RequiredError( + 'userId', + 'Required parameter "userId" was null or undefined when calling realmUsersUserIdOrgsOrgIdRolesPatch().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling realmUsersUserIdOrgsOrgIdRolesPatch().' + ); + } + + if (requestParameters['organizationRoleRepresentation'] == null) { + throw new runtime.RequiredError( + 'organizationRoleRepresentation', + 'Required parameter "organizationRoleRepresentation" was null or undefined when calling realmUsersUserIdOrgsOrgIdRolesPatch().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/users/{userId}/orgs/{orgId}/roles`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'PATCH', + headers: headerParameters, + query: queryParameters, + body: requestParameters['organizationRoleRepresentation']!.map(OrganizationRoleRepresentationToJSON), + }; + } + + /** + * Revoke organization roles from a user + */ + async realmUsersUserIdOrgsOrgIdRolesPatchRaw(requestParameters: RealmUsersUserIdOrgsOrgIdRolesPatchRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.realmUsersUserIdOrgsOrgIdRolesPatchRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(BulkResponseItemFromJSON)); + } + + /** + * Revoke organization roles from a user + */ + async realmUsersUserIdOrgsOrgIdRolesPatch(requestParameters: RealmUsersUserIdOrgsOrgIdRolesPatchRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const response = await this.realmUsersUserIdOrgsOrgIdRolesPatchRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for realmUsersUserIdOrgsOrgIdRolesPut without sending the request + */ + async realmUsersUserIdOrgsOrgIdRolesPutRequestOpts(requestParameters: RealmUsersUserIdOrgsOrgIdRolesPutRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling realmUsersUserIdOrgsOrgIdRolesPut().' + ); + } + + if (requestParameters['userId'] == null) { + throw new runtime.RequiredError( + 'userId', + 'Required parameter "userId" was null or undefined when calling realmUsersUserIdOrgsOrgIdRolesPut().' + ); + } + + if (requestParameters['orgId'] == null) { + throw new runtime.RequiredError( + 'orgId', + 'Required parameter "orgId" was null or undefined when calling realmUsersUserIdOrgsOrgIdRolesPut().' + ); + } + + if (requestParameters['organizationRoleRepresentation'] == null) { + throw new runtime.RequiredError( + 'organizationRoleRepresentation', + 'Required parameter "organizationRoleRepresentation" was null or undefined when calling realmUsersUserIdOrgsOrgIdRolesPut().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/users/{userId}/orgs/{orgId}/roles`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + urlPath = urlPath.replace('{userId}', encodeURIComponent(String(requestParameters['userId']))); + urlPath = urlPath.replace('{orgId}', encodeURIComponent(String(requestParameters['orgId']))); + + return { + path: urlPath, + method: 'PUT', + headers: headerParameters, + query: queryParameters, + body: requestParameters['organizationRoleRepresentation']!.map(OrganizationRoleRepresentationToJSON), + }; + } + + /** + * Grant a user organization roles + */ + async realmUsersUserIdOrgsOrgIdRolesPutRaw(requestParameters: RealmUsersUserIdOrgsOrgIdRolesPutRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise>> { + const requestOptions = await this.realmUsersUserIdOrgsOrgIdRolesPutRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(BulkResponseItemFromJSON)); + } + + /** + * Grant a user organization roles + */ + async realmUsersUserIdOrgsOrgIdRolesPut(requestParameters: RealmUsersUserIdOrgsOrgIdRolesPutRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const response = await this.realmUsersUserIdOrgsOrgIdRolesPutRaw(requestParameters, initOverrides); + return await response.value(); + } + + /** + * Creates request options for switchActiveOrganization without sending the request + */ + async switchActiveOrganizationRequestOpts(requestParameters: SwitchActiveOrganizationRequest): Promise { + if (requestParameters['realm'] == null) { + throw new runtime.RequiredError( + 'realm', + 'Required parameter "realm" was null or undefined when calling switchActiveOrganization().' + ); + } + + if (requestParameters['switchOrganizationRepresentation'] == null) { + throw new runtime.RequiredError( + 'switchOrganizationRepresentation', + 'Required parameter "switchOrganizationRepresentation" was null or undefined when calling switchActiveOrganization().' + ); + } + + const queryParameters: any = {}; + + const headerParameters: runtime.HTTPHeaders = {}; + + headerParameters['Content-Type'] = 'application/json'; + + if (this.configuration && this.configuration.accessToken) { + const token = this.configuration.accessToken; + const tokenString = await token("access_token", []); + + if (tokenString) { + headerParameters["Authorization"] = `Bearer ${tokenString}`; + } + } + + let urlPath = `/{realm}/users/switch-organization`; + urlPath = urlPath.replace('{realm}', encodeURIComponent(String(requestParameters['realm']))); + + return { + path: urlPath, + method: 'PUT', + headers: headerParameters, + query: queryParameters, + body: SwitchOrganizationRepresentationToJSON(requestParameters['switchOrganizationRepresentation']), + }; + } + + /** + * Switch the active organization context for the authenticated user + * Switch active organization for authenticated user + */ + async switchActiveOrganizationRaw(requestParameters: SwitchActiveOrganizationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise> { + const requestOptions = await this.switchActiveOrganizationRequestOpts(requestParameters); + const response = await this.request(requestOptions, initOverrides); + + return new runtime.JSONApiResponse(response, (jsonValue) => AccessTokenResponseFromJSON(jsonValue)); + } + + /** + * Switch the active organization context for the authenticated user + * Switch active organization for authenticated user + */ + async switchActiveOrganization(requestParameters: SwitchActiveOrganizationRequest, initOverrides?: RequestInit | runtime.InitOverrideFunction): Promise { + const response = await this.switchActiveOrganizationRaw(requestParameters, initOverrides); + return await response.value(); + } + } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/index.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/index.ts index 79a437c..abfc8bb 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/apis/index.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/apis/index.ts @@ -3,9 +3,11 @@ export * from './AttributesApi'; export * from './EventsApi'; export * from './IdentityProvidersApi'; +export * from './OrganizationApi'; export * from './OrganizationDomainsApi'; -export * from './OrganizationInvitationsApi'; +export * from './OrganizationInvitationApi'; export * from './OrganizationMembershipsApi'; export * from './OrganizationRolesApi'; +export * from './OrganizationSCIMApi'; export * from './OrganizationsApi'; export * from './UsersApi'; diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/AccessTokenResponse.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/AccessTokenResponse.ts new file mode 100644 index 0000000..2459919 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/AccessTokenResponse.ts @@ -0,0 +1,111 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * A freshly issued OIDC token set, reflecting the user's new active organization. The `refresh_token` is only present when the client is configured to use refresh tokens, and `id_token` only for OIDC requests. + * @export + * @interface AccessTokenResponse + */ +export interface AccessTokenResponse { + /** + * + */ + accessToken?: string; + /** + * + */ + expiresIn?: number; + /** + * + */ + refreshExpiresIn?: number; + /** + * + */ + refreshToken?: string; + /** + * + */ + tokenType?: string; + /** + * + */ + idToken?: string; + /** + * + */ + notBeforePolicy?: number; + /** + * + */ + sessionState?: string; + /** + * + */ + scope?: string; +} + +/** + * Check if a given object implements the AccessTokenResponse interface. + */ +export function instanceOfAccessTokenResponse(value: object): value is AccessTokenResponse { + return true; +} + +export function AccessTokenResponseFromJSON(json: any): AccessTokenResponse { + return AccessTokenResponseFromJSONTyped(json, false); +} + +export function AccessTokenResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): AccessTokenResponse { + if (json == null) { + return json; + } + return { + + 'accessToken': json['access_token'] == null ? undefined : json['access_token'], + 'expiresIn': json['expires_in'] == null ? undefined : json['expires_in'], + 'refreshExpiresIn': json['refresh_expires_in'] == null ? undefined : json['refresh_expires_in'], + 'refreshToken': json['refresh_token'] == null ? undefined : json['refresh_token'], + 'tokenType': json['token_type'] == null ? undefined : json['token_type'], + 'idToken': json['id_token'] == null ? undefined : json['id_token'], + 'notBeforePolicy': json['not-before-policy'] == null ? undefined : json['not-before-policy'], + 'sessionState': json['session_state'] == null ? undefined : json['session_state'], + 'scope': json['scope'] == null ? undefined : json['scope'], + }; +} + +export function AccessTokenResponseToJSON(json: any): AccessTokenResponse { + return AccessTokenResponseToJSONTyped(json, false); +} + +export function AccessTokenResponseToJSONTyped(value?: AccessTokenResponse | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'access_token': value['accessToken'], + 'expires_in': value['expiresIn'], + 'refresh_expires_in': value['refreshExpiresIn'], + 'refresh_token': value['refreshToken'], + 'token_type': value['tokenType'], + 'id_token': value['idToken'], + 'not-before-policy': value['notBeforePolicy'], + 'session_state': value['sessionState'], + 'scope': value['scope'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/AuthDetailsRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/AuthDetailsRepresentation.ts index 78c9f01..d0b2d63 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/AuthDetailsRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/AuthDetailsRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,38 +21,26 @@ import { mapValues } from '../runtime'; export interface AuthDetailsRepresentation { /** * - * @type {string} - * @memberof AuthDetailsRepresentation */ realmId?: string; /** * - * @type {string} - * @memberof AuthDetailsRepresentation */ clientId?: string; /** * - * @type {string} - * @memberof AuthDetailsRepresentation */ userId?: string; /** * - * @type {string} - * @memberof AuthDetailsRepresentation */ ipAddress?: string; /** * - * @type {string} - * @memberof AuthDetailsRepresentation */ username?: string; /** * - * @type {string} - * @memberof AuthDetailsRepresentation */ sessionId?: string; } @@ -83,11 +71,11 @@ export function AuthDetailsRepresentationFromJSONTyped(json: any, ignoreDiscrimi }; } - export function AuthDetailsRepresentationToJSON(json: any): AuthDetailsRepresentation { - return AuthDetailsRepresentationToJSONTyped(json, false); - } +export function AuthDetailsRepresentationToJSON(json: any): AuthDetailsRepresentation { + return AuthDetailsRepresentationToJSONTyped(json, false); +} - export function AuthDetailsRepresentationToJSONTyped(value?: AuthDetailsRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function AuthDetailsRepresentationToJSONTyped(value?: AuthDetailsRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/BulkResponseItem.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/BulkResponseItem.ts new file mode 100644 index 0000000..e9af62e --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/BulkResponseItem.ts @@ -0,0 +1,75 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface BulkResponseItem + */ +export interface BulkResponseItem { + /** + * + */ + status?: number; + /** + * + */ + error?: string; + /** + * + */ + item?: object; +} + +/** + * Check if a given object implements the BulkResponseItem interface. + */ +export function instanceOfBulkResponseItem(value: object): value is BulkResponseItem { + return true; +} + +export function BulkResponseItemFromJSON(json: any): BulkResponseItem { + return BulkResponseItemFromJSONTyped(json, false); +} + +export function BulkResponseItemFromJSONTyped(json: any, ignoreDiscriminator: boolean): BulkResponseItem { + if (json == null) { + return json; + } + return { + + 'status': json['status'] == null ? undefined : json['status'], + 'error': json['error'] == null ? undefined : json['error'], + 'item': json['item'] == null ? undefined : json['item'], + }; +} + +export function BulkResponseItemToJSON(json: any): BulkResponseItem { + return BulkResponseItemToJSONTyped(json, false); +} + +export function BulkResponseItemToJSONTyped(value?: BulkResponseItem | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'status': value['status'], + 'error': value['error'], + 'item': value['item'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/CreatePortalLinkForm.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/CreatePortalLinkForm.ts new file mode 100644 index 0000000..f72ef4a --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/CreatePortalLinkForm.ts @@ -0,0 +1,63 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface CreatePortalLinkForm + */ +export interface CreatePortalLinkForm { + /** + * + */ + userId?: string; +} + +/** + * Check if a given object implements the CreatePortalLinkForm interface. + */ +export function instanceOfCreatePortalLinkForm(value: object): value is CreatePortalLinkForm { + return true; +} + +export function CreatePortalLinkFormFromJSON(json: any): CreatePortalLinkForm { + return CreatePortalLinkFormFromJSONTyped(json, false); +} + +export function CreatePortalLinkFormFromJSONTyped(json: any, ignoreDiscriminator: boolean): CreatePortalLinkForm { + if (json == null) { + return json; + } + return { + + 'userId': json['userId'] == null ? undefined : json['userId'], + }; +} + +export function CreatePortalLinkFormToJSON(json: any): CreatePortalLinkForm { + return CreatePortalLinkFormToJSONTyped(json, false); +} + +export function CreatePortalLinkFormToJSONTyped(value?: CreatePortalLinkForm | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'userId': value['userId'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/CredentialRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/CredentialRepresentation.ts new file mode 100644 index 0000000..8d694e0 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/CredentialRepresentation.ts @@ -0,0 +1,69 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface CredentialRepresentation + */ +export interface CredentialRepresentation { + /** + * + */ + type?: string; + /** + * + */ + value?: string; +} + +/** + * Check if a given object implements the CredentialRepresentation interface. + */ +export function instanceOfCredentialRepresentation(value: object): value is CredentialRepresentation { + return true; +} + +export function CredentialRepresentationFromJSON(json: any): CredentialRepresentation { + return CredentialRepresentationFromJSONTyped(json, false); +} + +export function CredentialRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): CredentialRepresentation { + if (json == null) { + return json; + } + return { + + 'type': json['type'] == null ? undefined : json['type'], + 'value': json['value'] == null ? undefined : json['value'], + }; +} + +export function CredentialRepresentationToJSON(json: any): CredentialRepresentation { + return CredentialRepresentationToJSONTyped(json, false); +} + +export function CredentialRepresentationToJSONTyped(value?: CredentialRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'type': value['type'], + 'value': value['value'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/EventRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/EventRepresentation.ts index 8641aab..75c498d 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/EventRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/EventRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -29,74 +29,58 @@ import { export interface EventRepresentation { /** * - * @type {string} - * @memberof EventRepresentation + */ + id?: string; + /** + * */ uid?: string; /** * - * @type {number} - * @memberof EventRepresentation */ time?: number; /** * - * @type {string} - * @memberof EventRepresentation */ realmId?: string; /** * - * @type {string} - * @memberof EventRepresentation + */ + realmName?: string; + /** + * */ organizationId?: string; /** * - * @type {string} - * @memberof EventRepresentation */ type?: string; /** * - * @type {string} - * @memberof EventRepresentation */ representation?: string; /** * - * @type {string} - * @memberof EventRepresentation */ operationType?: string; /** * - * @type {string} - * @memberof EventRepresentation */ resourcePath?: string; /** * - * @type {string} - * @memberof EventRepresentation */ resourceType?: string; /** * - * @type {string} - * @memberof EventRepresentation */ error?: string; /** * - * @type {AuthDetailsRepresentation} - * @memberof EventRepresentation */ authDetails?: AuthDetailsRepresentation; /** * - * @type {{ [key: string]: any; }} - * @memberof EventRepresentation */ details?: { [key: string]: any; }; } @@ -118,9 +102,11 @@ export function EventRepresentationFromJSONTyped(json: any, ignoreDiscriminator: } return { + 'id': json['id'] == null ? undefined : json['id'], 'uid': json['uid'] == null ? undefined : json['uid'], 'time': json['time'] == null ? undefined : json['time'], 'realmId': json['realmId'] == null ? undefined : json['realmId'], + 'realmName': json['realmName'] == null ? undefined : json['realmName'], 'organizationId': json['organizationId'] == null ? undefined : json['organizationId'], 'type': json['type'] == null ? undefined : json['type'], 'representation': json['representation'] == null ? undefined : json['representation'], @@ -133,20 +119,22 @@ export function EventRepresentationFromJSONTyped(json: any, ignoreDiscriminator: }; } - export function EventRepresentationToJSON(json: any): EventRepresentation { - return EventRepresentationToJSONTyped(json, false); - } +export function EventRepresentationToJSON(json: any): EventRepresentation { + return EventRepresentationToJSONTyped(json, false); +} - export function EventRepresentationToJSONTyped(value?: EventRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function EventRepresentationToJSONTyped(value?: EventRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } return { + 'id': value['id'], 'uid': value['uid'], 'time': value['time'], 'realmId': value['realmId'], + 'realmName': value['realmName'], 'organizationId': value['organizationId'], 'type': value['type'], 'representation': value['representation'], diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/ExternalBasicScimAuth.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/ExternalBasicScimAuth.ts new file mode 100644 index 0000000..f22d3be --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/ExternalBasicScimAuth.ts @@ -0,0 +1,92 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * HTTP Basic auth. The password is hashed with Argon2id before + * storage. + * + * @export + * @interface ExternalBasicScimAuth + */ +export interface ExternalBasicScimAuth { + /** + * + */ + type: ExternalBasicScimAuthTypeEnum; + /** + * Username for HTTP Basic auth. Stored in cleartext. + */ + username?: string; + /** + * Password for HTTP Basic auth. Cleartext on submit; hashed at + * rest. Omit on update to keep the existing password. + * + */ + password?: string; +} + + +/** + * @export + */ +export const ExternalBasicScimAuthTypeEnum = { + ExternalBasic: 'EXTERNAL_BASIC', +} as const; +export type ExternalBasicScimAuthTypeEnum = typeof ExternalBasicScimAuthTypeEnum[keyof typeof ExternalBasicScimAuthTypeEnum]; + + +/** + * Check if a given object implements the ExternalBasicScimAuth interface. + */ +export function instanceOfExternalBasicScimAuth(value: object): value is ExternalBasicScimAuth { + if (!('type' in value) || value['type'] === undefined) return false; + if (value['type'] !== 'EXTERNAL_BASIC') return false; + + return true; +} + +export function ExternalBasicScimAuthFromJSON(json: any): ExternalBasicScimAuth { + return ExternalBasicScimAuthFromJSONTyped(json, false); +} + +export function ExternalBasicScimAuthFromJSONTyped(json: any, ignoreDiscriminator: boolean): ExternalBasicScimAuth { + if (json == null) { + return json; + } + return { + + 'type': json['type'], + 'username': json['username'] == null ? undefined : json['username'], + 'password': json['password'] == null ? undefined : json['password'], + }; +} + +export function ExternalBasicScimAuthToJSON(json: any): ExternalBasicScimAuth { + return ExternalBasicScimAuthToJSONTyped(json, false); +} + +export function ExternalBasicScimAuthToJSONTyped(value?: ExternalBasicScimAuth | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'type': value['type'], + 'username': value['username'], + 'password': value['password'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/ExternalJwtScimAuth.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/ExternalJwtScimAuth.ts new file mode 100644 index 0000000..ec06c4b --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/ExternalJwtScimAuth.ts @@ -0,0 +1,98 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * Validates an inbound JWT issued by an external IdP. The token's + * issuer and audience must match the configured values, and the + * signature is verified against keys fetched from the configured + * JWKS URI. + * + * @export + * @interface ExternalJwtScimAuth + */ +export interface ExternalJwtScimAuth { + /** + * + */ + type: ExternalJwtScimAuthTypeEnum; + /** + * Expected `iss` claim. Must exactly match the upstream IdP's issuer URL. + */ + issuer?: string; + /** + * Expected `aud` claim. + */ + audience?: string; + /** + * URL the server fetches to validate the JWT signature. + */ + jwksUri?: string; +} + + +/** + * @export + */ +export const ExternalJwtScimAuthTypeEnum = { + ExternalJwt: 'EXTERNAL_JWT', +} as const; +export type ExternalJwtScimAuthTypeEnum = typeof ExternalJwtScimAuthTypeEnum[keyof typeof ExternalJwtScimAuthTypeEnum]; + + +/** + * Check if a given object implements the ExternalJwtScimAuth interface. + */ +export function instanceOfExternalJwtScimAuth(value: object): value is ExternalJwtScimAuth { + if (!('type' in value) || value['type'] === undefined) return false; + if (value['type'] !== 'EXTERNAL_JWT') return false; + + return true; +} + +export function ExternalJwtScimAuthFromJSON(json: any): ExternalJwtScimAuth { + return ExternalJwtScimAuthFromJSONTyped(json, false); +} + +export function ExternalJwtScimAuthFromJSONTyped(json: any, ignoreDiscriminator: boolean): ExternalJwtScimAuth { + if (json == null) { + return json; + } + return { + + 'type': json['type'], + 'issuer': json['issuer'] == null ? undefined : json['issuer'], + 'audience': json['audience'] == null ? undefined : json['audience'], + 'jwksUri': json['jwks_uri'] == null ? undefined : json['jwks_uri'], + }; +} + +export function ExternalJwtScimAuthToJSON(json: any): ExternalJwtScimAuth { + return ExternalJwtScimAuthToJSONTyped(json, false); +} + +export function ExternalJwtScimAuthToJSONTyped(value?: ExternalJwtScimAuth | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'type': value['type'], + 'issuer': value['issuer'], + 'audience': value['audience'], + 'jwks_uri': value['jwksUri'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/ExternalSecretScimAuth.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/ExternalSecretScimAuth.ts new file mode 100644 index 0000000..d8d5aab --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/ExternalSecretScimAuth.ts @@ -0,0 +1,87 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * Bearer-style shared secret. The client sends + * `Authorization: Bearer `; the server compares the value + * against a stored Argon2id hash. + * + * @export + * @interface ExternalSecretScimAuth + */ +export interface ExternalSecretScimAuth { + /** + * + */ + type: ExternalSecretScimAuthTypeEnum; + /** + * Random opaque value. Cleartext on submit; hashed at rest. Omit + * on update to keep the existing secret. + * + */ + sharedSecret?: string; +} + + +/** + * @export + */ +export const ExternalSecretScimAuthTypeEnum = { + ExternalSecret: 'EXTERNAL_SECRET', +} as const; +export type ExternalSecretScimAuthTypeEnum = typeof ExternalSecretScimAuthTypeEnum[keyof typeof ExternalSecretScimAuthTypeEnum]; + + +/** + * Check if a given object implements the ExternalSecretScimAuth interface. + */ +export function instanceOfExternalSecretScimAuth(value: object): value is ExternalSecretScimAuth { + if (!('type' in value) || value['type'] === undefined) return false; + if (value['type'] !== 'EXTERNAL_SECRET') return false; + + return true; +} + +export function ExternalSecretScimAuthFromJSON(json: any): ExternalSecretScimAuth { + return ExternalSecretScimAuthFromJSONTyped(json, false); +} + +export function ExternalSecretScimAuthFromJSONTyped(json: any, ignoreDiscriminator: boolean): ExternalSecretScimAuth { + if (json == null) { + return json; + } + return { + + 'type': json['type'], + 'sharedSecret': json['shared_secret'] == null ? undefined : json['shared_secret'], + }; +} + +export function ExternalSecretScimAuthToJSON(json: any): ExternalSecretScimAuth { + return ExternalSecretScimAuthToJSONTyped(json, false); +} + +export function ExternalSecretScimAuthToJSONTyped(value?: ExternalSecretScimAuth | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'type': value['type'], + 'shared_secret': value['sharedSecret'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/IdentityProviderMapperRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/IdentityProviderMapperRepresentation.ts index 5fc2c92..a564910 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/IdentityProviderMapperRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/IdentityProviderMapperRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,32 +21,22 @@ import { mapValues } from '../runtime'; export interface IdentityProviderMapperRepresentation { /** * - * @type {{ [key: string]: any; }} - * @memberof IdentityProviderMapperRepresentation */ config?: { [key: string]: any; }; /** * - * @type {string} - * @memberof IdentityProviderMapperRepresentation */ id?: string; /** * - * @type {string} - * @memberof IdentityProviderMapperRepresentation */ identityProviderAlias?: string; /** * - * @type {string} - * @memberof IdentityProviderMapperRepresentation */ identityProviderMapper?: string; /** * - * @type {string} - * @memberof IdentityProviderMapperRepresentation */ name?: string; } @@ -76,11 +66,11 @@ export function IdentityProviderMapperRepresentationFromJSONTyped(json: any, ign }; } - export function IdentityProviderMapperRepresentationToJSON(json: any): IdentityProviderMapperRepresentation { - return IdentityProviderMapperRepresentationToJSONTyped(json, false); - } +export function IdentityProviderMapperRepresentationToJSON(json: any): IdentityProviderMapperRepresentation { + return IdentityProviderMapperRepresentationToJSONTyped(json, false); +} - export function IdentityProviderMapperRepresentationToJSONTyped(value?: IdentityProviderMapperRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function IdentityProviderMapperRepresentationToJSONTyped(value?: IdentityProviderMapperRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/IdentityProviderRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/IdentityProviderRepresentation.ts index 39ed0a4..5a7fa41 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/IdentityProviderRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/IdentityProviderRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,74 +21,50 @@ import { mapValues } from '../runtime'; export interface IdentityProviderRepresentation { /** * - * @type {boolean} - * @memberof IdentityProviderRepresentation */ addReadTokenRoleOnCreate?: boolean; /** * - * @type {string} - * @memberof IdentityProviderRepresentation */ alias?: string; /** * - * @type {{ [key: string]: any; }} - * @memberof IdentityProviderRepresentation */ config?: { [key: string]: any; }; /** * - * @type {string} - * @memberof IdentityProviderRepresentation */ displayName?: string; /** * - * @type {boolean} - * @memberof IdentityProviderRepresentation */ enabled?: boolean; /** * - * @type {string} - * @memberof IdentityProviderRepresentation */ firstBrokerLoginFlowAlias?: string; /** * - * @type {string} - * @memberof IdentityProviderRepresentation */ internalId?: string; /** * - * @type {boolean} - * @memberof IdentityProviderRepresentation */ linkOnly?: boolean; /** * - * @type {string} - * @memberof IdentityProviderRepresentation */ postBrokerLoginFlowAlias?: string; /** * - * @type {string} - * @memberof IdentityProviderRepresentation */ providerId?: string; /** * - * @type {boolean} - * @memberof IdentityProviderRepresentation */ storeToken?: boolean; /** * - * @type {boolean} - * @memberof IdentityProviderRepresentation */ trustEmail?: boolean; } @@ -125,11 +101,11 @@ export function IdentityProviderRepresentationFromJSONTyped(json: any, ignoreDis }; } - export function IdentityProviderRepresentationToJSON(json: any): IdentityProviderRepresentation { - return IdentityProviderRepresentationToJSONTyped(json, false); - } +export function IdentityProviderRepresentationToJSON(json: any): IdentityProviderRepresentation { + return IdentityProviderRepresentationToJSONTyped(json, false); +} - export function IdentityProviderRepresentationToJSONTyped(value?: IdentityProviderRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function IdentityProviderRepresentationToJSONTyped(value?: IdentityProviderRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/ImportOrganizationsForm.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/ImportOrganizationsForm.ts new file mode 100644 index 0000000..6a8dd3c --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/ImportOrganizationsForm.ts @@ -0,0 +1,63 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface ImportOrganizationsForm + */ +export interface ImportOrganizationsForm { + /** + * JSON file containing organizations export + */ + file?: Blob; +} + +/** + * Check if a given object implements the ImportOrganizationsForm interface. + */ +export function instanceOfImportOrganizationsForm(value: object): value is ImportOrganizationsForm { + return true; +} + +export function ImportOrganizationsFormFromJSON(json: any): ImportOrganizationsForm { + return ImportOrganizationsFormFromJSONTyped(json, false); +} + +export function ImportOrganizationsFormFromJSONTyped(json: any, ignoreDiscriminator: boolean): ImportOrganizationsForm { + if (json == null) { + return json; + } + return { + + 'file': json['file'] == null ? undefined : json['file'], + }; +} + +export function ImportOrganizationsFormToJSON(json: any): ImportOrganizationsForm { + return ImportOrganizationsFormToJSONTyped(json, false); +} + +export function ImportOrganizationsFormToJSONTyped(value?: ImportOrganizationsForm | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'file': value['file'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/InvitationRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/InvitationRepresentation.ts index f9ed357..9519e60 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/InvitationRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/InvitationRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,34 +21,36 @@ import { mapValues } from '../runtime'; export interface InvitationRepresentation { /** * - * @type {string} - * @memberof InvitationRepresentation */ id?: string; /** * - * @type {string} - * @memberof InvitationRepresentation + */ + createdAt?: string; + /** + * */ email?: string; /** * - * @type {string} - * @memberof InvitationRepresentation */ inviterId?: string; /** * - * @type {string} - * @memberof InvitationRepresentation + */ + invitationUrl?: string; + /** + * */ organizationId?: string; /** * - * @type {Array} - * @memberof InvitationRepresentation */ roles?: Array; + /** + * + */ + attributes?: { [key: string]: Array; }; } /** @@ -69,18 +71,21 @@ export function InvitationRepresentationFromJSONTyped(json: any, ignoreDiscrimin return { 'id': json['id'] == null ? undefined : json['id'], + 'createdAt': json['createdAt'] == null ? undefined : json['createdAt'], 'email': json['email'] == null ? undefined : json['email'], 'inviterId': json['inviterId'] == null ? undefined : json['inviterId'], + 'invitationUrl': json['invitationUrl'] == null ? undefined : json['invitationUrl'], 'organizationId': json['organizationId'] == null ? undefined : json['organizationId'], 'roles': json['roles'] == null ? undefined : json['roles'], + 'attributes': json['attributes'] == null ? undefined : json['attributes'], }; } - export function InvitationRepresentationToJSON(json: any): InvitationRepresentation { - return InvitationRepresentationToJSONTyped(json, false); - } +export function InvitationRepresentationToJSON(json: any): InvitationRepresentation { + return InvitationRepresentationToJSONTyped(json, false); +} - export function InvitationRepresentationToJSONTyped(value?: InvitationRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function InvitationRepresentationToJSONTyped(value?: InvitationRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } @@ -88,10 +93,13 @@ export function InvitationRepresentationFromJSONTyped(json: any, ignoreDiscrimin return { 'id': value['id'], + 'createdAt': value['createdAt'], 'email': value['email'], 'inviterId': value['inviterId'], + 'invitationUrl': value['invitationUrl'], 'organizationId': value['organizationId'], 'roles': value['roles'], + 'attributes': value['attributes'], }; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/InvitationRequestRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/InvitationRequestRepresentation.ts index 746f1d6..bee99a0 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/InvitationRequestRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/InvitationRequestRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,34 +21,28 @@ import { mapValues } from '../runtime'; export interface InvitationRequestRepresentation { /** * - * @type {string} - * @memberof InvitationRequestRepresentation */ email?: string; /** * - * @type {boolean} - * @memberof InvitationRequestRepresentation */ send?: boolean; /** * - * @type {string} - * @memberof InvitationRequestRepresentation */ inviterId?: string; /** * - * @type {string} - * @memberof InvitationRequestRepresentation */ redirectUri?: string; /** * - * @type {Array} - * @memberof InvitationRequestRepresentation */ roles?: Array; + /** + * + */ + attributes?: { [key: string]: Array; }; } /** @@ -73,14 +67,15 @@ export function InvitationRequestRepresentationFromJSONTyped(json: any, ignoreDi 'inviterId': json['inviterId'] == null ? undefined : json['inviterId'], 'redirectUri': json['redirectUri'] == null ? undefined : json['redirectUri'], 'roles': json['roles'] == null ? undefined : json['roles'], + 'attributes': json['attributes'] == null ? undefined : json['attributes'], }; } - export function InvitationRequestRepresentationToJSON(json: any): InvitationRequestRepresentation { - return InvitationRequestRepresentationToJSONTyped(json, false); - } +export function InvitationRequestRepresentationToJSON(json: any): InvitationRequestRepresentation { + return InvitationRequestRepresentationToJSONTyped(json, false); +} - export function InvitationRequestRepresentationToJSONTyped(value?: InvitationRequestRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function InvitationRequestRepresentationToJSONTyped(value?: InvitationRequestRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } @@ -92,6 +87,7 @@ export function InvitationRequestRepresentationFromJSONTyped(json: any, ignoreDi 'inviterId': value['inviterId'], 'redirectUri': value['redirectUri'], 'roles': value['roles'], + 'attributes': value['attributes'], }; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/KeycloakScimAuth.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/KeycloakScimAuth.ts new file mode 100644 index 0000000..f8108b4 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/KeycloakScimAuth.ts @@ -0,0 +1,79 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * Authenticates inbound SCIM calls with a Keycloak-issued access + * token (Bearer). The caller must hold the realm-management roles + * required to manage members of the organization. + * + * @export + * @interface KeycloakScimAuth + */ +export interface KeycloakScimAuth { + /** + * + */ + type: KeycloakScimAuthTypeEnum; +} + + +/** + * @export + */ +export const KeycloakScimAuthTypeEnum = { + Keycloak: 'KEYCLOAK', +} as const; +export type KeycloakScimAuthTypeEnum = typeof KeycloakScimAuthTypeEnum[keyof typeof KeycloakScimAuthTypeEnum]; + + +/** + * Check if a given object implements the KeycloakScimAuth interface. + */ +export function instanceOfKeycloakScimAuth(value: object): value is KeycloakScimAuth { + if (!('type' in value) || value['type'] === undefined) return false; + if (value['type'] !== 'KEYCLOAK') return false; + + return true; +} + +export function KeycloakScimAuthFromJSON(json: any): KeycloakScimAuth { + return KeycloakScimAuthFromJSONTyped(json, false); +} + +export function KeycloakScimAuthFromJSONTyped(json: any, ignoreDiscriminator: boolean): KeycloakScimAuth { + if (json == null) { + return json; + } + return { + + 'type': json['type'], + }; +} + +export function KeycloakScimAuthToJSON(json: any): KeycloakScimAuth { + return KeycloakScimAuthToJSONTyped(json, false); +} + +export function KeycloakScimAuthToJSONTyped(value?: KeycloakScimAuth | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'type': value['type'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/LinkIdentityProviderRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/LinkIdentityProviderRepresentation.ts new file mode 100644 index 0000000..24c257d --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/LinkIdentityProviderRepresentation.ts @@ -0,0 +1,75 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface LinkIdentityProviderRepresentation + */ +export interface LinkIdentityProviderRepresentation { + /** + * + */ + alias?: string; + /** + * + */ + postBrokerFlow?: string; + /** + * + */ + syncMode?: string; +} + +/** + * Check if a given object implements the LinkIdentityProviderRepresentation interface. + */ +export function instanceOfLinkIdentityProviderRepresentation(value: object): value is LinkIdentityProviderRepresentation { + return true; +} + +export function LinkIdentityProviderRepresentationFromJSON(json: any): LinkIdentityProviderRepresentation { + return LinkIdentityProviderRepresentationFromJSONTyped(json, false); +} + +export function LinkIdentityProviderRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): LinkIdentityProviderRepresentation { + if (json == null) { + return json; + } + return { + + 'alias': json['alias'] == null ? undefined : json['alias'], + 'postBrokerFlow': json['post_broker_flow'] == null ? undefined : json['post_broker_flow'], + 'syncMode': json['sync_mode'] == null ? undefined : json['sync_mode'], + }; +} + +export function LinkIdentityProviderRepresentationToJSON(json: any): LinkIdentityProviderRepresentation { + return LinkIdentityProviderRepresentationToJSONTyped(json, false); +} + +export function LinkIdentityProviderRepresentationToJSONTyped(value?: LinkIdentityProviderRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'alias': value['alias'], + 'post_broker_flow': value['postBrokerFlow'], + 'sync_mode': value['syncMode'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/MagicLinkRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/MagicLinkRepresentation.ts deleted file mode 100644 index 6147934..0000000 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/MagicLinkRepresentation.ts +++ /dev/null @@ -1,108 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -/** - * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | - * - * The version of the OpenAPI document: v1 - * - * - * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). - * https://openapi-generator.tech - * Do not edit the class manually. - */ - -import { mapValues } from '../runtime'; -/** - * - * @export - * @interface MagicLinkRepresentation - */ -export interface MagicLinkRepresentation { - /** - * - * @type {string} - * @memberof MagicLinkRepresentation - */ - email: string; - /** - * - * @type {string} - * @memberof MagicLinkRepresentation - */ - clientId: string; - /** - * - * @type {string} - * @memberof MagicLinkRepresentation - */ - redirectUri: string; - /** - * - * @type {number} - * @memberof MagicLinkRepresentation - */ - expirationSeconds?: number; - /** - * - * @type {boolean} - * @memberof MagicLinkRepresentation - */ - forceCreate?: boolean; - /** - * - * @type {boolean} - * @memberof MagicLinkRepresentation - */ - sendEmail?: boolean; -} - -/** - * Check if a given object implements the MagicLinkRepresentation interface. - */ -export function instanceOfMagicLinkRepresentation(value: object): value is MagicLinkRepresentation { - if (!('email' in value) || value['email'] === undefined) return false; - if (!('clientId' in value) || value['clientId'] === undefined) return false; - if (!('redirectUri' in value) || value['redirectUri'] === undefined) return false; - return true; -} - -export function MagicLinkRepresentationFromJSON(json: any): MagicLinkRepresentation { - return MagicLinkRepresentationFromJSONTyped(json, false); -} - -export function MagicLinkRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): MagicLinkRepresentation { - if (json == null) { - return json; - } - return { - - 'email': json['email'], - 'clientId': json['client_id'], - 'redirectUri': json['redirect_uri'], - 'expirationSeconds': json['expiration_seconds'] == null ? undefined : json['expiration_seconds'], - 'forceCreate': json['force_create'] == null ? undefined : json['force_create'], - 'sendEmail': json['send_email'] == null ? undefined : json['send_email'], - }; -} - - export function MagicLinkRepresentationToJSON(json: any): MagicLinkRepresentation { - return MagicLinkRepresentationToJSONTyped(json, false); - } - - export function MagicLinkRepresentationToJSONTyped(value?: MagicLinkRepresentation | null, ignoreDiscriminator: boolean = false): any { - if (value == null) { - return value; - } - - return { - - 'email': value['email'], - 'client_id': value['clientId'], - 'redirect_uri': value['redirectUri'], - 'expiration_seconds': value['expirationSeconds'], - 'force_create': value['forceCreate'], - 'send_email': value['sendEmail'], - }; -} - diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/MagicLinkRequest.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/MagicLinkRequest.ts new file mode 100644 index 0000000..340ebbd --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/MagicLinkRequest.ts @@ -0,0 +1,161 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface MagicLinkRequest + */ +export interface MagicLinkRequest { + /** + * + */ + email?: string; + /** + * + */ + clientId: string; + /** + * + */ + redirectUri: string; + /** + * + */ + username?: string; + /** + * + */ + expirationSeconds?: number; + /** + * + */ + forceCreate?: boolean; + /** + * + */ + sendEmail?: boolean; + /** + * + */ + updateProfile?: boolean; + /** + * + */ + updatePassword?: boolean; + /** + * + */ + scope?: string; + /** + * + */ + nonce?: string; + /** + * + */ + state?: string; + /** + * + */ + codeChallenge?: string; + /** + * + */ + codeChallengeMethod?: string; + /** + * + */ + rememberMe?: boolean; + /** + * + */ + reusable?: boolean; + /** + * + */ + responseMode?: string; +} + +/** + * Check if a given object implements the MagicLinkRequest interface. + */ +export function instanceOfMagicLinkRequest(value: object): value is MagicLinkRequest { + if ((!('clientId' in (value as Record)) && !('client_id' in (value as Record))) || ((value as Record)['clientId'] === undefined && (value as Record)['client_id'] === undefined)) return false; + if ((!('redirectUri' in (value as Record)) && !('redirect_uri' in (value as Record))) || ((value as Record)['redirectUri'] === undefined && (value as Record)['redirect_uri'] === undefined)) return false; + return true; +} + +export function MagicLinkRequestFromJSON(json: any): MagicLinkRequest { + return MagicLinkRequestFromJSONTyped(json, false); +} + +export function MagicLinkRequestFromJSONTyped(json: any, ignoreDiscriminator: boolean): MagicLinkRequest { + if (json == null) { + return json; + } + return { + + 'email': json['email'] == null ? undefined : json['email'], + 'clientId': json['client_id'], + 'redirectUri': json['redirect_uri'], + 'username': json['username'] == null ? undefined : json['username'], + 'expirationSeconds': json['expiration_seconds'] == null ? undefined : json['expiration_seconds'], + 'forceCreate': json['force_create'] == null ? undefined : json['force_create'], + 'sendEmail': json['send_email'] == null ? undefined : json['send_email'], + 'updateProfile': json['update_profile'] == null ? undefined : json['update_profile'], + 'updatePassword': json['update_password'] == null ? undefined : json['update_password'], + 'scope': json['scope'] == null ? undefined : json['scope'], + 'nonce': json['nonce'] == null ? undefined : json['nonce'], + 'state': json['state'] == null ? undefined : json['state'], + 'codeChallenge': json['code_challenge'] == null ? undefined : json['code_challenge'], + 'codeChallengeMethod': json['code_challenge_method'] == null ? undefined : json['code_challenge_method'], + 'rememberMe': json['remember_me'] == null ? undefined : json['remember_me'], + 'reusable': json['reusable'] == null ? undefined : json['reusable'], + 'responseMode': json['response_mode'] == null ? undefined : json['response_mode'], + }; +} + +export function MagicLinkRequestToJSON(json: any): MagicLinkRequest { + return MagicLinkRequestToJSONTyped(json, false); +} + +export function MagicLinkRequestToJSONTyped(value?: MagicLinkRequest | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'email': value['email'], + 'client_id': value['clientId'], + 'redirect_uri': value['redirectUri'], + 'username': value['username'], + 'expiration_seconds': value['expirationSeconds'], + 'force_create': value['forceCreate'], + 'send_email': value['sendEmail'], + 'update_profile': value['updateProfile'], + 'update_password': value['updatePassword'], + 'scope': value['scope'], + 'nonce': value['nonce'], + 'state': value['state'], + 'code_challenge': value['codeChallenge'], + 'code_challenge_method': value['codeChallengeMethod'], + 'remember_me': value['rememberMe'], + 'reusable': value['reusable'], + 'response_mode': value['responseMode'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/MagicLinkResponse.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/MagicLinkResponse.ts new file mode 100644 index 0000000..41a3c9b --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/MagicLinkResponse.ts @@ -0,0 +1,75 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface MagicLinkResponse + */ +export interface MagicLinkResponse { + /** + * + */ + userId?: string; + /** + * + */ + link?: string; + /** + * + */ + sent?: boolean; +} + +/** + * Check if a given object implements the MagicLinkResponse interface. + */ +export function instanceOfMagicLinkResponse(value: object): value is MagicLinkResponse { + return true; +} + +export function MagicLinkResponseFromJSON(json: any): MagicLinkResponse { + return MagicLinkResponseFromJSONTyped(json, false); +} + +export function MagicLinkResponseFromJSONTyped(json: any, ignoreDiscriminator: boolean): MagicLinkResponse { + if (json == null) { + return json; + } + return { + + 'userId': json['user_id'] == null ? undefined : json['user_id'], + 'link': json['link'] == null ? undefined : json['link'], + 'sent': json['sent'] == null ? undefined : json['sent'], + }; +} + +export function MagicLinkResponseToJSON(json: any): MagicLinkResponse { + return MagicLinkResponseToJSONTyped(json, false); +} + +export function MagicLinkResponseToJSONTyped(value?: MagicLinkResponse | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'user_id': value['userId'], + 'link': value['link'], + 'sent': value['sent'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/MyOrganizationRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/MyOrganizationRepresentation.ts index c65ce36..aaa990f 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/MyOrganizationRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/MyOrganizationRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,32 +21,22 @@ import { mapValues } from '../runtime'; export interface MyOrganizationRepresentation { /** * - * @type {string} - * @memberof MyOrganizationRepresentation */ name?: string; /** * - * @type {string} - * @memberof MyOrganizationRepresentation */ displayName?: string; /** * - * @type {string} - * @memberof MyOrganizationRepresentation */ url?: string; /** * - * @type {{ [key: string]: Array; }} - * @memberof MyOrganizationRepresentation */ attributes?: { [key: string]: Array; }; /** * - * @type {Array} - * @memberof MyOrganizationRepresentation */ roles?: Array; } @@ -76,11 +66,11 @@ export function MyOrganizationRepresentationFromJSONTyped(json: any, ignoreDiscr }; } - export function MyOrganizationRepresentationToJSON(json: any): MyOrganizationRepresentation { - return MyOrganizationRepresentationToJSONTyped(json, false); - } +export function MyOrganizationRepresentationToJSON(json: any): MyOrganizationRepresentation { + return MyOrganizationRepresentationToJSONTyped(json, false); +} - export function MyOrganizationRepresentationToJSONTyped(value?: MyOrganizationRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function MyOrganizationRepresentationToJSONTyped(value?: MyOrganizationRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationConfigRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationConfigRepresentation.ts new file mode 100644 index 0000000..b2fda54 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationConfigRepresentation.ts @@ -0,0 +1,109 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface OrganizationConfigRepresentation + */ +export interface OrganizationConfigRepresentation { + /** + * Whether to create a default admin user for new organizations + */ + createAdminUser?: boolean; + /** + * Whether identity providers can be shared across organizations + */ + sharedIdps?: boolean; + /** + * Whether admin events are enabled for organization operations + */ + adminEventsEnabled?: boolean; + /** + * Whether user events are enabled for organization operations + */ + eventsEnabled?: boolean; + /** + * Default post broker login flow for organization identity providers + */ + defaultPostBrokerFlow?: string; + /** + * Default sync mode for organization identity providers + */ + defaultSyncMode?: string; + /** + * Additional configuration attributes + */ + attributes?: { [key: string]: Array; }; + /** + * Realm-level feature flag that turns on per-organization SCIM 2.0 + * provisioning. When false (the default) the organization SCIM + * configuration endpoints under `/{realm}/orgs/{orgId}/scim` + * return 404 and the SCIM tab is hidden in the Admin UI. + * + */ + scimEnabled?: boolean; +} + +/** + * Check if a given object implements the OrganizationConfigRepresentation interface. + */ +export function instanceOfOrganizationConfigRepresentation(value: object): value is OrganizationConfigRepresentation { + return true; +} + +export function OrganizationConfigRepresentationFromJSON(json: any): OrganizationConfigRepresentation { + return OrganizationConfigRepresentationFromJSONTyped(json, false); +} + +export function OrganizationConfigRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): OrganizationConfigRepresentation { + if (json == null) { + return json; + } + return { + + 'createAdminUser': json['createAdminUser'] == null ? undefined : json['createAdminUser'], + 'sharedIdps': json['sharedIdps'] == null ? undefined : json['sharedIdps'], + 'adminEventsEnabled': json['adminEventsEnabled'] == null ? undefined : json['adminEventsEnabled'], + 'eventsEnabled': json['eventsEnabled'] == null ? undefined : json['eventsEnabled'], + 'defaultPostBrokerFlow': json['defaultPostBrokerFlow'] == null ? undefined : json['defaultPostBrokerFlow'], + 'defaultSyncMode': json['defaultSyncMode'] == null ? undefined : json['defaultSyncMode'], + 'attributes': json['attributes'] == null ? undefined : json['attributes'], + 'scimEnabled': json['scimEnabled'] == null ? undefined : json['scimEnabled'], + }; +} + +export function OrganizationConfigRepresentationToJSON(json: any): OrganizationConfigRepresentation { + return OrganizationConfigRepresentationToJSONTyped(json, false); +} + +export function OrganizationConfigRepresentationToJSONTyped(value?: OrganizationConfigRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'createAdminUser': value['createAdminUser'], + 'sharedIdps': value['sharedIdps'], + 'adminEventsEnabled': value['adminEventsEnabled'], + 'eventsEnabled': value['eventsEnabled'], + 'defaultPostBrokerFlow': value['defaultPostBrokerFlow'], + 'defaultSyncMode': value['defaultSyncMode'], + 'attributes': value['attributes'], + 'scimEnabled': value['scimEnabled'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationDomainRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationDomainRepresentation.ts index d0b43b5..8631b33 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationDomainRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationDomainRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,40 +21,30 @@ import { mapValues } from '../runtime'; export interface OrganizationDomainRepresentation { /** * - * @type {string} - * @memberof OrganizationDomainRepresentation */ - domainName?: string; + domainName: string; /** * - * @type {boolean} - * @memberof OrganizationDomainRepresentation */ - verified?: boolean; + verified: boolean; /** * - * @type {string} - * @memberof OrganizationDomainRepresentation */ - recordKey?: string; + recordKey: string; /** * - * @type {string} - * @memberof OrganizationDomainRepresentation */ - recordValue?: string; - /** - * - * @type {string} - * @memberof OrganizationDomainRepresentation - */ - type?: string; + recordValue: string; } /** * Check if a given object implements the OrganizationDomainRepresentation interface. */ export function instanceOfOrganizationDomainRepresentation(value: object): value is OrganizationDomainRepresentation { + if ((!('domainName' in (value as Record)) && !('domain_name' in (value as Record))) || ((value as Record)['domainName'] === undefined && (value as Record)['domain_name'] === undefined)) return false; + if (!('verified' in value) || value['verified'] === undefined) return false; + if ((!('recordKey' in (value as Record)) && !('record_key' in (value as Record))) || ((value as Record)['recordKey'] === undefined && (value as Record)['record_key'] === undefined)) return false; + if ((!('recordValue' in (value as Record)) && !('record_value' in (value as Record))) || ((value as Record)['recordValue'] === undefined && (value as Record)['record_value'] === undefined)) return false; return true; } @@ -68,19 +58,18 @@ export function OrganizationDomainRepresentationFromJSONTyped(json: any, ignoreD } return { - 'domainName': json['domain_name'] == null ? undefined : json['domain_name'], - 'verified': json['verified'] == null ? undefined : json['verified'], - 'recordKey': json['record_key'] == null ? undefined : json['record_key'], - 'recordValue': json['record_value'] == null ? undefined : json['record_value'], - 'type': json['type'] == null ? undefined : json['type'], + 'domainName': json['domain_name'], + 'verified': json['verified'], + 'recordKey': json['record_key'], + 'recordValue': json['record_value'], }; } - export function OrganizationDomainRepresentationToJSON(json: any): OrganizationDomainRepresentation { - return OrganizationDomainRepresentationToJSONTyped(json, false); - } +export function OrganizationDomainRepresentationToJSON(json: any): OrganizationDomainRepresentation { + return OrganizationDomainRepresentationToJSONTyped(json, false); +} - export function OrganizationDomainRepresentationToJSONTyped(value?: OrganizationDomainRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function OrganizationDomainRepresentationToJSONTyped(value?: OrganizationDomainRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } @@ -91,7 +80,6 @@ export function OrganizationDomainRepresentationFromJSONTyped(json: any, ignoreD 'verified': value['verified'], 'record_key': value['recordKey'], 'record_value': value['recordValue'], - 'type': value['type'], }; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationExportRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationExportRepresentation.ts new file mode 100644 index 0000000..ab37468 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationExportRepresentation.ts @@ -0,0 +1,139 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +import type { OrganizationRoleRepresentation } from './OrganizationRoleRepresentation'; +import { + OrganizationRoleRepresentationFromJSON, + OrganizationRoleRepresentationFromJSONTyped, + OrganizationRoleRepresentationToJSON, + OrganizationRoleRepresentationToJSONTyped, +} from './OrganizationRoleRepresentation'; +import type { IdentityProviderRepresentation } from './IdentityProviderRepresentation'; +import { + IdentityProviderRepresentationFromJSON, + IdentityProviderRepresentationFromJSONTyped, + IdentityProviderRepresentationToJSON, + IdentityProviderRepresentationToJSONTyped, +} from './IdentityProviderRepresentation'; +import type { OrganizationExportRepresentationAllOfMembers } from './OrganizationExportRepresentationAllOfMembers'; +import { + OrganizationExportRepresentationAllOfMembersFromJSON, + OrganizationExportRepresentationAllOfMembersFromJSONTyped, + OrganizationExportRepresentationAllOfMembersToJSON, + OrganizationExportRepresentationAllOfMembersToJSONTyped, +} from './OrganizationExportRepresentationAllOfMembers'; + +/** + * + * @export + * @interface OrganizationExportRepresentation + */ +export interface OrganizationExportRepresentation { + /** + * + */ + id?: string; + /** + * + */ + name?: string; + /** + * + */ + displayName?: string; + /** + * + */ + url?: string; + /** + * + */ + realm?: string; + /** + * + */ + domains?: Array; + /** + * + */ + attributes?: { [key: string]: Array; }; + /** + * + */ + roles?: Array; + /** + * + */ + identityProviders?: Array; + /** + * + */ + members?: Array; +} + +/** + * Check if a given object implements the OrganizationExportRepresentation interface. + */ +export function instanceOfOrganizationExportRepresentation(value: object): value is OrganizationExportRepresentation { + return true; +} + +export function OrganizationExportRepresentationFromJSON(json: any): OrganizationExportRepresentation { + return OrganizationExportRepresentationFromJSONTyped(json, false); +} + +export function OrganizationExportRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): OrganizationExportRepresentation { + if (json == null) { + return json; + } + return { + + 'id': json['id'] == null ? undefined : json['id'], + 'name': json['name'] == null ? undefined : json['name'], + 'displayName': json['displayName'] == null ? undefined : json['displayName'], + 'url': json['url'] == null ? undefined : json['url'], + 'realm': json['realm'] == null ? undefined : json['realm'], + 'domains': json['domains'] == null ? undefined : json['domains'], + 'attributes': json['attributes'] == null ? undefined : json['attributes'], + 'roles': json['roles'] == null ? undefined : ((json['roles'] as Array).map(OrganizationRoleRepresentationFromJSON)), + 'identityProviders': json['identityProviders'] == null ? undefined : ((json['identityProviders'] as Array).map(IdentityProviderRepresentationFromJSON)), + 'members': json['members'] == null ? undefined : ((json['members'] as Array).map(OrganizationExportRepresentationAllOfMembersFromJSON)), + }; +} + +export function OrganizationExportRepresentationToJSON(json: any): OrganizationExportRepresentation { + return OrganizationExportRepresentationToJSONTyped(json, false); +} + +export function OrganizationExportRepresentationToJSONTyped(value?: OrganizationExportRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'id': value['id'], + 'name': value['name'], + 'displayName': value['displayName'], + 'url': value['url'], + 'realm': value['realm'], + 'domains': value['domains'], + 'attributes': value['attributes'], + 'roles': value['roles'] == null ? undefined : ((value['roles'] as Array).map(OrganizationRoleRepresentationToJSON)), + 'identityProviders': value['identityProviders'] == null ? undefined : ((value['identityProviders'] as Array).map(IdentityProviderRepresentationToJSON)), + 'members': value['members'] == null ? undefined : ((value['members'] as Array).map(OrganizationExportRepresentationAllOfMembersToJSON)), + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationExportRepresentationAllOfMembers.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationExportRepresentationAllOfMembers.ts new file mode 100644 index 0000000..a2b1c11 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationExportRepresentationAllOfMembers.ts @@ -0,0 +1,75 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface OrganizationExportRepresentationAllOfMembers + */ +export interface OrganizationExportRepresentationAllOfMembers { + /** + * + */ + userId?: string; + /** + * + */ + email?: string; + /** + * + */ + roles?: Array; +} + +/** + * Check if a given object implements the OrganizationExportRepresentationAllOfMembers interface. + */ +export function instanceOfOrganizationExportRepresentationAllOfMembers(value: object): value is OrganizationExportRepresentationAllOfMembers { + return true; +} + +export function OrganizationExportRepresentationAllOfMembersFromJSON(json: any): OrganizationExportRepresentationAllOfMembers { + return OrganizationExportRepresentationAllOfMembersFromJSONTyped(json, false); +} + +export function OrganizationExportRepresentationAllOfMembersFromJSONTyped(json: any, ignoreDiscriminator: boolean): OrganizationExportRepresentationAllOfMembers { + if (json == null) { + return json; + } + return { + + 'userId': json['userId'] == null ? undefined : json['userId'], + 'email': json['email'] == null ? undefined : json['email'], + 'roles': json['roles'] == null ? undefined : json['roles'], + }; +} + +export function OrganizationExportRepresentationAllOfMembersToJSON(json: any): OrganizationExportRepresentationAllOfMembers { + return OrganizationExportRepresentationAllOfMembersToJSONTyped(json, false); +} + +export function OrganizationExportRepresentationAllOfMembersToJSONTyped(value?: OrganizationExportRepresentationAllOfMembers | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'userId': value['userId'], + 'email': value['email'], + 'roles': value['roles'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationMemberAttributeRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationMemberAttributeRepresentation.ts new file mode 100644 index 0000000..c97624e --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationMemberAttributeRepresentation.ts @@ -0,0 +1,63 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface OrganizationMemberAttributeRepresentation + */ +export interface OrganizationMemberAttributeRepresentation { + /** + * + */ + attributes?: { [key: string]: Array; }; +} + +/** + * Check if a given object implements the OrganizationMemberAttributeRepresentation interface. + */ +export function instanceOfOrganizationMemberAttributeRepresentation(value: object): value is OrganizationMemberAttributeRepresentation { + return true; +} + +export function OrganizationMemberAttributeRepresentationFromJSON(json: any): OrganizationMemberAttributeRepresentation { + return OrganizationMemberAttributeRepresentationFromJSONTyped(json, false); +} + +export function OrganizationMemberAttributeRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): OrganizationMemberAttributeRepresentation { + if (json == null) { + return json; + } + return { + + 'attributes': json['attributes'] == null ? undefined : json['attributes'], + }; +} + +export function OrganizationMemberAttributeRepresentationToJSON(json: any): OrganizationMemberAttributeRepresentation { + return OrganizationMemberAttributeRepresentationToJSONTyped(json, false); +} + +export function OrganizationMemberAttributeRepresentationToJSONTyped(value?: OrganizationMemberAttributeRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'attributes': value['attributes'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationRepresentation.ts index e147867..57e6a39 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,44 +21,30 @@ import { mapValues } from '../runtime'; export interface OrganizationRepresentation { /** * - * @type {string} - * @memberof OrganizationRepresentation */ id?: string; /** * - * @type {string} - * @memberof OrganizationRepresentation */ name?: string; /** * - * @type {string} - * @memberof OrganizationRepresentation */ displayName?: string; /** * - * @type {string} - * @memberof OrganizationRepresentation */ url?: string; /** * - * @type {string} - * @memberof OrganizationRepresentation */ realm?: string; /** * - * @type {Array} - * @memberof OrganizationRepresentation */ domains?: Array; /** * - * @type {{ [key: string]: Array; }} - * @memberof OrganizationRepresentation */ attributes?: { [key: string]: Array; }; } @@ -90,11 +76,11 @@ export function OrganizationRepresentationFromJSONTyped(json: any, ignoreDiscrim }; } - export function OrganizationRepresentationToJSON(json: any): OrganizationRepresentation { - return OrganizationRepresentationToJSONTyped(json, false); - } +export function OrganizationRepresentationToJSON(json: any): OrganizationRepresentation { + return OrganizationRepresentationToJSONTyped(json, false); +} - export function OrganizationRepresentationToJSONTyped(value?: OrganizationRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function OrganizationRepresentationToJSONTyped(value?: OrganizationRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationRoleRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationRoleRepresentation.ts index 9c3f9e3..7e059b2 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationRoleRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationRoleRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,20 +21,14 @@ import { mapValues } from '../runtime'; export interface OrganizationRoleRepresentation { /** * - * @type {string} - * @memberof OrganizationRoleRepresentation */ id?: string; /** * - * @type {string} - * @memberof OrganizationRoleRepresentation */ name?: string; /** * - * @type {string} - * @memberof OrganizationRoleRepresentation */ description?: string; } @@ -62,11 +56,11 @@ export function OrganizationRoleRepresentationFromJSONTyped(json: any, ignoreDis }; } - export function OrganizationRoleRepresentationToJSON(json: any): OrganizationRoleRepresentation { - return OrganizationRoleRepresentationToJSONTyped(json, false); - } +export function OrganizationRoleRepresentationToJSON(json: any): OrganizationRoleRepresentation { + return OrganizationRoleRepresentationToJSONTyped(json, false); +} - export function OrganizationRoleRepresentationToJSONTyped(value?: OrganizationRoleRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function OrganizationRoleRepresentationToJSONTyped(value?: OrganizationRoleRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationScimAuth.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationScimAuth.ts new file mode 100644 index 0000000..9d5cb53 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationScimAuth.ts @@ -0,0 +1,98 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime'; +import type { ExternalBasicScimAuth } from './ExternalBasicScimAuth'; +import { + instanceOfExternalBasicScimAuth, + ExternalBasicScimAuthFromJSON, + ExternalBasicScimAuthFromJSONTyped, + ExternalBasicScimAuthToJSON, +} from './ExternalBasicScimAuth'; +import type { ExternalJwtScimAuth } from './ExternalJwtScimAuth'; +import { + instanceOfExternalJwtScimAuth, + ExternalJwtScimAuthFromJSON, + ExternalJwtScimAuthFromJSONTyped, + ExternalJwtScimAuthToJSON, +} from './ExternalJwtScimAuth'; +import type { ExternalSecretScimAuth } from './ExternalSecretScimAuth'; +import { + instanceOfExternalSecretScimAuth, + ExternalSecretScimAuthFromJSON, + ExternalSecretScimAuthFromJSONTyped, + ExternalSecretScimAuthToJSON, +} from './ExternalSecretScimAuth'; +import type { KeycloakScimAuth } from './KeycloakScimAuth'; +import { + instanceOfKeycloakScimAuth, + KeycloakScimAuthFromJSON, + KeycloakScimAuthFromJSONTyped, + KeycloakScimAuthToJSON, +} from './KeycloakScimAuth'; + +/** + * @type OrganizationScimAuth + * Polymorphic authentication configuration for the inbound SCIM + * endpoint. The `type` field discriminates the variant; the remaining + * fields depend on the variant chosen. + * + * @export + */ +export type OrganizationScimAuth = { type: 'EXTERNAL_BASIC' } & ExternalBasicScimAuth | { type: 'EXTERNAL_JWT' } & ExternalJwtScimAuth | { type: 'EXTERNAL_SECRET' } & ExternalSecretScimAuth | { type: 'KEYCLOAK' } & KeycloakScimAuth; + +export function OrganizationScimAuthFromJSON(json: any): OrganizationScimAuth { + return OrganizationScimAuthFromJSONTyped(json, false); +} + +export function OrganizationScimAuthFromJSONTyped(json: any, ignoreDiscriminator: boolean): OrganizationScimAuth { + if (json == null) { + return json; + } + switch (json['type']) { + case 'EXTERNAL_BASIC': + return Object.assign({}, ExternalBasicScimAuthFromJSONTyped(json, true), { type: 'EXTERNAL_BASIC' } as const); + case 'EXTERNAL_JWT': + return Object.assign({}, ExternalJwtScimAuthFromJSONTyped(json, true), { type: 'EXTERNAL_JWT' } as const); + case 'EXTERNAL_SECRET': + return Object.assign({}, ExternalSecretScimAuthFromJSONTyped(json, true), { type: 'EXTERNAL_SECRET' } as const); + case 'KEYCLOAK': + return Object.assign({}, KeycloakScimAuthFromJSONTyped(json, true), { type: 'KEYCLOAK' } as const); + default: + return json; + } +} + +export function OrganizationScimAuthToJSON(json: any): any { + return OrganizationScimAuthToJSONTyped(json, false); +} + +export function OrganizationScimAuthToJSONTyped(value?: OrganizationScimAuth | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + switch (value['type']) { + case 'EXTERNAL_BASIC': + return Object.assign({}, ExternalBasicScimAuthToJSON(value), { 'type': 'EXTERNAL_BASIC' } as const); + case 'EXTERNAL_JWT': + return Object.assign({}, ExternalJwtScimAuthToJSON(value), { 'type': 'EXTERNAL_JWT' } as const); + case 'EXTERNAL_SECRET': + return Object.assign({}, ExternalSecretScimAuthToJSON(value), { 'type': 'EXTERNAL_SECRET' } as const); + case 'KEYCLOAK': + return Object.assign({}, KeycloakScimAuthToJSON(value), { 'type': 'KEYCLOAK' } as const); + default: + return value; + } +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationScimRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationScimRepresentation.ts new file mode 100644 index 0000000..5d9dbae --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationScimRepresentation.ts @@ -0,0 +1,101 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +import type { OrganizationScimAuth } from './OrganizationScimAuth'; +import { + OrganizationScimAuthFromJSON, + OrganizationScimAuthFromJSONTyped, + OrganizationScimAuthToJSON, + OrganizationScimAuthToJSONTyped, +} from './OrganizationScimAuth'; + +/** + * Per-organization SCIM 2.0 service-provider configuration. One of these + * backs the SCIM endpoint at + * `{authServerUrl}/realms/{realm}/scim/v2/organizations/{orgId}/`. + * + * @export + * @interface OrganizationScimRepresentation + */ +export interface OrganizationScimRepresentation { + /** + * Whether the organization's SCIM endpoint accepts inbound traffic. + * Turn this off to pause provisioning without losing the + * configuration. + * + */ + enabled?: boolean; + /** + * When true, the provisioned user's `username` mirrors their + * `email`, and subsequent SCIM update operations do not change + * the username. + * + */ + emailAsUsername?: boolean; + /** + * When true, provisioned users are federated with the + * organization's configured identity provider so they can sign in + * via the org's SSO immediately after provisioning. + * + */ + linkIdp?: boolean; + /** + * + */ + auth?: OrganizationScimAuth; +} + +/** + * Check if a given object implements the OrganizationScimRepresentation interface. + */ +export function instanceOfOrganizationScimRepresentation(value: object): value is OrganizationScimRepresentation { + return true; +} + +export function OrganizationScimRepresentationFromJSON(json: any): OrganizationScimRepresentation { + return OrganizationScimRepresentationFromJSONTyped(json, false); +} + +export function OrganizationScimRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): OrganizationScimRepresentation { + if (json == null) { + return json; + } + return { + + 'enabled': json['enabled'] == null ? undefined : json['enabled'], + 'emailAsUsername': json['email_as_username'] == null ? undefined : json['email_as_username'], + 'linkIdp': json['link_idp'] == null ? undefined : json['link_idp'], + 'auth': json['auth'] == null ? undefined : OrganizationScimAuthFromJSON(json['auth']), + }; +} + +export function OrganizationScimRepresentationToJSON(json: any): OrganizationScimRepresentation { + return OrganizationScimRepresentationToJSONTyped(json, false); +} + +export function OrganizationScimRepresentationToJSONTyped(value?: OrganizationScimRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'enabled': value['enabled'], + 'email_as_username': value['emailAsUsername'], + 'link_idp': value['linkIdp'], + 'auth': OrganizationScimAuthToJSON(value['auth']), + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsConfigRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsConfigRepresentation.ts new file mode 100644 index 0000000..4d7f759 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsConfigRepresentation.ts @@ -0,0 +1,69 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface OrganizationsConfigRepresentation + */ +export interface OrganizationsConfigRepresentation { + /** + * Whether to create a default admin user for new organizations + */ + createAdminUserEnabled?: boolean; + /** + * Whether identity providers can be shared across organizations + */ + sharedIdpsEnabled?: boolean; +} + +/** + * Check if a given object implements the OrganizationsConfigRepresentation interface. + */ +export function instanceOfOrganizationsConfigRepresentation(value: object): value is OrganizationsConfigRepresentation { + return true; +} + +export function OrganizationsConfigRepresentationFromJSON(json: any): OrganizationsConfigRepresentation { + return OrganizationsConfigRepresentationFromJSONTyped(json, false); +} + +export function OrganizationsConfigRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): OrganizationsConfigRepresentation { + if (json == null) { + return json; + } + return { + + 'createAdminUserEnabled': json['createAdminUserEnabled'] == null ? undefined : json['createAdminUserEnabled'], + 'sharedIdpsEnabled': json['sharedIdpsEnabled'] == null ? undefined : json['sharedIdpsEnabled'], + }; +} + +export function OrganizationsConfigRepresentationToJSON(json: any): OrganizationsConfigRepresentation { + return OrganizationsConfigRepresentationToJSONTyped(json, false); +} + +export function OrganizationsConfigRepresentationToJSONTyped(value?: OrganizationsConfigRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'createAdminUserEnabled': value['createAdminUserEnabled'], + 'sharedIdpsEnabled': value['sharedIdpsEnabled'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsExportRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsExportRepresentation.ts new file mode 100644 index 0000000..548ad44 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsExportRepresentation.ts @@ -0,0 +1,102 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues, parseDate, parseDateTime, serializeDate, serializeDateTime } from '../runtime'; +import type { OrganizationExportRepresentation } from './OrganizationExportRepresentation'; +import { + OrganizationExportRepresentationFromJSON, + OrganizationExportRepresentationFromJSONTyped, + OrganizationExportRepresentationToJSON, + OrganizationExportRepresentationToJSONTyped, +} from './OrganizationExportRepresentation'; +import type { OrganizationsConfigRepresentation } from './OrganizationsConfigRepresentation'; +import { + OrganizationsConfigRepresentationFromJSON, + OrganizationsConfigRepresentationFromJSONTyped, + OrganizationsConfigRepresentationToJSON, + OrganizationsConfigRepresentationToJSONTyped, +} from './OrganizationsConfigRepresentation'; + +/** + * + * @export + * @interface OrganizationsExportRepresentation + */ +export interface OrganizationsExportRepresentation { + /** + * Export format version + */ + version?: string; + /** + * Source realm name + */ + realm?: string; + /** + * Export timestamp + */ + exportedAt?: Date; + /** + * + */ + organizations?: Array; + /** + * + */ + config?: OrganizationsConfigRepresentation; +} + +/** + * Check if a given object implements the OrganizationsExportRepresentation interface. + */ +export function instanceOfOrganizationsExportRepresentation(value: object): value is OrganizationsExportRepresentation { + return true; +} + +export function OrganizationsExportRepresentationFromJSON(json: any): OrganizationsExportRepresentation { + return OrganizationsExportRepresentationFromJSONTyped(json, false); +} + +export function OrganizationsExportRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): OrganizationsExportRepresentation { + if (json == null) { + return json; + } + return { + + 'version': json['version'] == null ? undefined : json['version'], + 'realm': json['realm'] == null ? undefined : json['realm'], + 'exportedAt': json['exportedAt'] == null ? undefined : (parseDateTime(json['exportedAt'])), + 'organizations': json['organizations'] == null ? undefined : ((json['organizations'] as Array).map(OrganizationExportRepresentationFromJSON)), + 'config': json['config'] == null ? undefined : OrganizationsConfigRepresentationFromJSON(json['config']), + }; +} + +export function OrganizationsExportRepresentationToJSON(json: any): OrganizationsExportRepresentation { + return OrganizationsExportRepresentationToJSONTyped(json, false); +} + +export function OrganizationsExportRepresentationToJSONTyped(value?: OrganizationsExportRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'version': value['version'], + 'realm': value['realm'], + 'exportedAt': value['exportedAt'] == null ? value['exportedAt'] : serializeDateTime(value['exportedAt']), + 'organizations': value['organizations'] == null ? undefined : ((value['organizations'] as Array).map(OrganizationExportRepresentationToJSON)), + 'config': OrganizationsConfigRepresentationToJSON(value['config']), + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsImportRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsImportRepresentation.ts new file mode 100644 index 0000000..50178f4 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsImportRepresentation.ts @@ -0,0 +1,90 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +import type { OrganizationExportRepresentation } from './OrganizationExportRepresentation'; +import { + OrganizationExportRepresentationFromJSON, + OrganizationExportRepresentationFromJSONTyped, + OrganizationExportRepresentationToJSON, + OrganizationExportRepresentationToJSONTyped, +} from './OrganizationExportRepresentation'; +import type { OrganizationsConfigRepresentation } from './OrganizationsConfigRepresentation'; +import { + OrganizationsConfigRepresentationFromJSON, + OrganizationsConfigRepresentationFromJSONTyped, + OrganizationsConfigRepresentationToJSON, + OrganizationsConfigRepresentationToJSONTyped, +} from './OrganizationsConfigRepresentation'; + +/** + * + * @export + * @interface OrganizationsImportRepresentation + */ +export interface OrganizationsImportRepresentation { + /** + * Import format version + */ + version?: string; + /** + * + */ + organizations?: Array; + /** + * + */ + config?: OrganizationsConfigRepresentation; +} + +/** + * Check if a given object implements the OrganizationsImportRepresentation interface. + */ +export function instanceOfOrganizationsImportRepresentation(value: object): value is OrganizationsImportRepresentation { + return true; +} + +export function OrganizationsImportRepresentationFromJSON(json: any): OrganizationsImportRepresentation { + return OrganizationsImportRepresentationFromJSONTyped(json, false); +} + +export function OrganizationsImportRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): OrganizationsImportRepresentation { + if (json == null) { + return json; + } + return { + + 'version': json['version'] == null ? undefined : json['version'], + 'organizations': json['organizations'] == null ? undefined : ((json['organizations'] as Array).map(OrganizationExportRepresentationFromJSON)), + 'config': json['config'] == null ? undefined : OrganizationsConfigRepresentationFromJSON(json['config']), + }; +} + +export function OrganizationsImportRepresentationToJSON(json: any): OrganizationsImportRepresentation { + return OrganizationsImportRepresentationToJSONTyped(json, false); +} + +export function OrganizationsImportRepresentationToJSONTyped(value?: OrganizationsImportRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'version': value['version'], + 'organizations': value['organizations'] == null ? undefined : ((value['organizations'] as Array).map(OrganizationExportRepresentationToJSON)), + 'config': OrganizationsConfigRepresentationToJSON(value['config']), + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsImportResultRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsImportResultRepresentation.ts new file mode 100644 index 0000000..6b343fd --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsImportResultRepresentation.ts @@ -0,0 +1,89 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +import type { OrganizationsImportResultRepresentationErrorsInner } from './OrganizationsImportResultRepresentationErrorsInner'; +import { + OrganizationsImportResultRepresentationErrorsInnerFromJSON, + OrganizationsImportResultRepresentationErrorsInnerFromJSONTyped, + OrganizationsImportResultRepresentationErrorsInnerToJSON, + OrganizationsImportResultRepresentationErrorsInnerToJSONTyped, +} from './OrganizationsImportResultRepresentationErrorsInner'; + +/** + * + * @export + * @interface OrganizationsImportResultRepresentation + */ +export interface OrganizationsImportResultRepresentation { + /** + * Number of organizations successfully imported + */ + imported?: number; + /** + * Number of organizations updated + */ + updated?: number; + /** + * Number of organizations skipped + */ + skipped?: number; + /** + * + */ + errors?: Array; +} + +/** + * Check if a given object implements the OrganizationsImportResultRepresentation interface. + */ +export function instanceOfOrganizationsImportResultRepresentation(value: object): value is OrganizationsImportResultRepresentation { + return true; +} + +export function OrganizationsImportResultRepresentationFromJSON(json: any): OrganizationsImportResultRepresentation { + return OrganizationsImportResultRepresentationFromJSONTyped(json, false); +} + +export function OrganizationsImportResultRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): OrganizationsImportResultRepresentation { + if (json == null) { + return json; + } + return { + + 'imported': json['imported'] == null ? undefined : json['imported'], + 'updated': json['updated'] == null ? undefined : json['updated'], + 'skipped': json['skipped'] == null ? undefined : json['skipped'], + 'errors': json['errors'] == null ? undefined : ((json['errors'] as Array).map(OrganizationsImportResultRepresentationErrorsInnerFromJSON)), + }; +} + +export function OrganizationsImportResultRepresentationToJSON(json: any): OrganizationsImportResultRepresentation { + return OrganizationsImportResultRepresentationToJSONTyped(json, false); +} + +export function OrganizationsImportResultRepresentationToJSONTyped(value?: OrganizationsImportResultRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'imported': value['imported'], + 'updated': value['updated'], + 'skipped': value['skipped'], + 'errors': value['errors'] == null ? undefined : ((value['errors'] as Array).map(OrganizationsImportResultRepresentationErrorsInnerToJSON)), + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsImportResultRepresentationErrorsInner.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsImportResultRepresentationErrorsInner.ts new file mode 100644 index 0000000..bf1e0ac --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/OrganizationsImportResultRepresentationErrorsInner.ts @@ -0,0 +1,69 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface OrganizationsImportResultRepresentationErrorsInner + */ +export interface OrganizationsImportResultRepresentationErrorsInner { + /** + * + */ + organizationName?: string; + /** + * + */ + error?: string; +} + +/** + * Check if a given object implements the OrganizationsImportResultRepresentationErrorsInner interface. + */ +export function instanceOfOrganizationsImportResultRepresentationErrorsInner(value: object): value is OrganizationsImportResultRepresentationErrorsInner { + return true; +} + +export function OrganizationsImportResultRepresentationErrorsInnerFromJSON(json: any): OrganizationsImportResultRepresentationErrorsInner { + return OrganizationsImportResultRepresentationErrorsInnerFromJSONTyped(json, false); +} + +export function OrganizationsImportResultRepresentationErrorsInnerFromJSONTyped(json: any, ignoreDiscriminator: boolean): OrganizationsImportResultRepresentationErrorsInner { + if (json == null) { + return json; + } + return { + + 'organizationName': json['organizationName'] == null ? undefined : json['organizationName'], + 'error': json['error'] == null ? undefined : json['error'], + }; +} + +export function OrganizationsImportResultRepresentationErrorsInnerToJSON(json: any): OrganizationsImportResultRepresentationErrorsInner { + return OrganizationsImportResultRepresentationErrorsInnerToJSONTyped(json, false); +} + +export function OrganizationsImportResultRepresentationErrorsInnerToJSONTyped(value?: OrganizationsImportResultRepresentationErrorsInner | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'organizationName': value['organizationName'], + 'error': value['error'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/PortalLinkRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/PortalLinkRepresentation.ts index b350028..ec08ae5 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/PortalLinkRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/PortalLinkRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,20 +21,14 @@ import { mapValues } from '../runtime'; export interface PortalLinkRepresentation { /** * - * @type {string} - * @memberof PortalLinkRepresentation */ user?: string; /** * - * @type {string} - * @memberof PortalLinkRepresentation */ link?: string; /** * - * @type {string} - * @memberof PortalLinkRepresentation */ redirect?: string; } @@ -62,11 +56,11 @@ export function PortalLinkRepresentationFromJSONTyped(json: any, ignoreDiscrimin }; } - export function PortalLinkRepresentationToJSON(json: any): PortalLinkRepresentation { - return PortalLinkRepresentationToJSONTyped(json, false); - } +export function PortalLinkRepresentationToJSON(json: any): PortalLinkRepresentation { + return PortalLinkRepresentationToJSONTyped(json, false); +} - export function PortalLinkRepresentationToJSONTyped(value?: PortalLinkRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function PortalLinkRepresentationToJSONTyped(value?: PortalLinkRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/RealmAttributeRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/RealmAttributeRepresentation.ts index 290de0e..f084531 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/RealmAttributeRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/RealmAttributeRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,20 +21,14 @@ import { mapValues } from '../runtime'; export interface RealmAttributeRepresentation { /** * - * @type {string} - * @memberof RealmAttributeRepresentation */ name?: string; /** * - * @type {string} - * @memberof RealmAttributeRepresentation */ value?: string; /** * - * @type {string} - * @memberof RealmAttributeRepresentation */ realm?: string; } @@ -62,11 +56,11 @@ export function RealmAttributeRepresentationFromJSONTyped(json: any, ignoreDiscr }; } - export function RealmAttributeRepresentationToJSON(json: any): RealmAttributeRepresentation { - return RealmAttributeRepresentationToJSONTyped(json, false); - } +export function RealmAttributeRepresentationToJSON(json: any): RealmAttributeRepresentation { + return RealmAttributeRepresentationToJSONTyped(json, false); +} - export function RealmAttributeRepresentationToJSONTyped(value?: RealmAttributeRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function RealmAttributeRepresentationToJSONTyped(value?: RealmAttributeRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/SwitchOrganizationRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/SwitchOrganizationRepresentation.ts new file mode 100644 index 0000000..5f8316c --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/SwitchOrganizationRepresentation.ts @@ -0,0 +1,64 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface SwitchOrganizationRepresentation + */ +export interface SwitchOrganizationRepresentation { + /** + * The ID of the organization to switch to + */ + id: string; +} + +/** + * Check if a given object implements the SwitchOrganizationRepresentation interface. + */ +export function instanceOfSwitchOrganizationRepresentation(value: object): value is SwitchOrganizationRepresentation { + if (!('id' in value) || value['id'] === undefined) return false; + return true; +} + +export function SwitchOrganizationRepresentationFromJSON(json: any): SwitchOrganizationRepresentation { + return SwitchOrganizationRepresentationFromJSONTyped(json, false); +} + +export function SwitchOrganizationRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): SwitchOrganizationRepresentation { + if (json == null) { + return json; + } + return { + + 'id': json['id'], + }; +} + +export function SwitchOrganizationRepresentationToJSON(json: any): SwitchOrganizationRepresentation { + return SwitchOrganizationRepresentationToJSONTyped(json, false); +} + +export function SwitchOrganizationRepresentationToJSONTyped(value?: SwitchOrganizationRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'id': value['id'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserBriefRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserBriefRepresentation.ts new file mode 100644 index 0000000..263e03a --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserBriefRepresentation.ts @@ -0,0 +1,111 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +/** + * + * @export + * @interface UserBriefRepresentation + */ +export interface UserBriefRepresentation { + /** + * + */ + createdTimestamp?: number; + /** + * + */ + email?: string; + /** + * + */ + emailVerified?: boolean; + /** + * + */ + enabled?: boolean; + /** + * + */ + firstName?: string; + /** + * + */ + groups?: Array; + /** + * + */ + id?: string; + /** + * + */ + lastName?: string; + /** + * + */ + username?: string; +} + +/** + * Check if a given object implements the UserBriefRepresentation interface. + */ +export function instanceOfUserBriefRepresentation(value: object): value is UserBriefRepresentation { + return true; +} + +export function UserBriefRepresentationFromJSON(json: any): UserBriefRepresentation { + return UserBriefRepresentationFromJSONTyped(json, false); +} + +export function UserBriefRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): UserBriefRepresentation { + if (json == null) { + return json; + } + return { + + 'createdTimestamp': json['createdTimestamp'] == null ? undefined : json['createdTimestamp'], + 'email': json['email'] == null ? undefined : json['email'], + 'emailVerified': json['emailVerified'] == null ? undefined : json['emailVerified'], + 'enabled': json['enabled'] == null ? undefined : json['enabled'], + 'firstName': json['firstName'] == null ? undefined : json['firstName'], + 'groups': json['groups'] == null ? undefined : json['groups'], + 'id': json['id'] == null ? undefined : json['id'], + 'lastName': json['lastName'] == null ? undefined : json['lastName'], + 'username': json['username'] == null ? undefined : json['username'], + }; +} + +export function UserBriefRepresentationToJSON(json: any): UserBriefRepresentation { + return UserBriefRepresentationToJSONTyped(json, false); +} + +export function UserBriefRepresentationToJSONTyped(value?: UserBriefRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'createdTimestamp': value['createdTimestamp'], + 'email': value['email'], + 'emailVerified': value['emailVerified'], + 'enabled': value['enabled'], + 'firstName': value['firstName'], + 'groups': value['groups'], + 'id': value['id'], + 'lastName': value['lastName'], + 'username': value['username'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserRepresentation.ts index 2d2d28e..ca62772 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,62 +21,42 @@ import { mapValues } from '../runtime'; export interface UserRepresentation { /** * - * @type {{ [key: string]: any; }} - * @memberof UserRepresentation */ attributes?: { [key: string]: any; }; /** * - * @type {number} - * @memberof UserRepresentation */ createdTimestamp?: number; /** * - * @type {string} - * @memberof UserRepresentation */ email?: string; /** * - * @type {boolean} - * @memberof UserRepresentation */ emailVerified?: boolean; /** * - * @type {boolean} - * @memberof UserRepresentation */ enabled?: boolean; /** * - * @type {string} - * @memberof UserRepresentation */ firstName?: string; /** * - * @type {Array} - * @memberof UserRepresentation */ groups?: Array; /** * - * @type {string} - * @memberof UserRepresentation */ id?: string; /** * - * @type {string} - * @memberof UserRepresentation */ lastName?: string; /** * - * @type {string} - * @memberof UserRepresentation */ username?: string; } @@ -111,11 +91,11 @@ export function UserRepresentationFromJSONTyped(json: any, ignoreDiscriminator: }; } - export function UserRepresentationToJSON(json: any): UserRepresentation { - return UserRepresentationToJSONTyped(json, false); - } +export function UserRepresentationToJSON(json: any): UserRepresentation { + return UserRepresentationToJSONTyped(json, false); +} - export function UserRepresentationToJSONTyped(value?: UserRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function UserRepresentationToJSONTyped(value?: UserRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserWithOrgsBriefRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserWithOrgsBriefRepresentation.ts new file mode 100644 index 0000000..592b35f --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserWithOrgsBriefRepresentation.ts @@ -0,0 +1,125 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +import type { OrganizationRoleRepresentation } from './OrganizationRoleRepresentation'; +import { + OrganizationRoleRepresentationFromJSON, + OrganizationRoleRepresentationFromJSONTyped, + OrganizationRoleRepresentationToJSON, + OrganizationRoleRepresentationToJSONTyped, +} from './OrganizationRoleRepresentation'; + +/** + * + * @export + * @interface UserWithOrgsBriefRepresentation + */ +export interface UserWithOrgsBriefRepresentation { + /** + * + */ + createdTimestamp?: number; + /** + * + */ + email?: string; + /** + * + */ + emailVerified?: boolean; + /** + * + */ + enabled?: boolean; + /** + * + */ + firstName?: string; + /** + * + */ + groups?: Array; + /** + * + */ + id?: string; + /** + * + */ + lastName?: string; + /** + * + */ + username?: string; + /** + * + */ + organizations?: { [key: string]: Array; }; +} + +/** + * Check if a given object implements the UserWithOrgsBriefRepresentation interface. + */ +export function instanceOfUserWithOrgsBriefRepresentation(value: object): value is UserWithOrgsBriefRepresentation { + return true; +} + +export function UserWithOrgsBriefRepresentationFromJSON(json: any): UserWithOrgsBriefRepresentation { + return UserWithOrgsBriefRepresentationFromJSONTyped(json, false); +} + +export function UserWithOrgsBriefRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): UserWithOrgsBriefRepresentation { + if (json == null) { + return json; + } + return { + + 'createdTimestamp': json['createdTimestamp'] == null ? undefined : json['createdTimestamp'], + 'email': json['email'] == null ? undefined : json['email'], + 'emailVerified': json['emailVerified'] == null ? undefined : json['emailVerified'], + 'enabled': json['enabled'] == null ? undefined : json['enabled'], + 'firstName': json['firstName'] == null ? undefined : json['firstName'], + 'groups': json['groups'] == null ? undefined : json['groups'], + 'id': json['id'] == null ? undefined : json['id'], + 'lastName': json['lastName'] == null ? undefined : json['lastName'], + 'username': json['username'] == null ? undefined : json['username'], + 'organizations': json['organizations'] == null ? undefined : json['organizations'], + }; +} + +export function UserWithOrgsBriefRepresentationToJSON(json: any): UserWithOrgsBriefRepresentation { + return UserWithOrgsBriefRepresentationToJSONTyped(json, false); +} + +export function UserWithOrgsBriefRepresentationToJSONTyped(value?: UserWithOrgsBriefRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'createdTimestamp': value['createdTimestamp'], + 'email': value['email'], + 'emailVerified': value['emailVerified'], + 'enabled': value['enabled'], + 'firstName': value['firstName'], + 'groups': value['groups'], + 'id': value['id'], + 'lastName': value['lastName'], + 'username': value['username'], + 'organizations': value['organizations'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserWithOrgsRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserWithOrgsRepresentation.ts new file mode 100644 index 0000000..d68b2c7 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/UserWithOrgsRepresentation.ts @@ -0,0 +1,131 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +import type { OrganizationRoleRepresentation } from './OrganizationRoleRepresentation'; +import { + OrganizationRoleRepresentationFromJSON, + OrganizationRoleRepresentationFromJSONTyped, + OrganizationRoleRepresentationToJSON, + OrganizationRoleRepresentationToJSONTyped, +} from './OrganizationRoleRepresentation'; + +/** + * + * @export + * @interface UserWithOrgsRepresentation + */ +export interface UserWithOrgsRepresentation { + /** + * + */ + attributes?: { [key: string]: any; }; + /** + * + */ + createdTimestamp?: number; + /** + * + */ + email?: string; + /** + * + */ + emailVerified?: boolean; + /** + * + */ + enabled?: boolean; + /** + * + */ + firstName?: string; + /** + * + */ + groups?: Array; + /** + * + */ + id?: string; + /** + * + */ + lastName?: string; + /** + * + */ + username?: string; + /** + * + */ + organizations?: { [key: string]: Array; }; +} + +/** + * Check if a given object implements the UserWithOrgsRepresentation interface. + */ +export function instanceOfUserWithOrgsRepresentation(value: object): value is UserWithOrgsRepresentation { + return true; +} + +export function UserWithOrgsRepresentationFromJSON(json: any): UserWithOrgsRepresentation { + return UserWithOrgsRepresentationFromJSONTyped(json, false); +} + +export function UserWithOrgsRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): UserWithOrgsRepresentation { + if (json == null) { + return json; + } + return { + + 'attributes': json['attributes'] == null ? undefined : json['attributes'], + 'createdTimestamp': json['createdTimestamp'] == null ? undefined : json['createdTimestamp'], + 'email': json['email'] == null ? undefined : json['email'], + 'emailVerified': json['emailVerified'] == null ? undefined : json['emailVerified'], + 'enabled': json['enabled'] == null ? undefined : json['enabled'], + 'firstName': json['firstName'] == null ? undefined : json['firstName'], + 'groups': json['groups'] == null ? undefined : json['groups'], + 'id': json['id'] == null ? undefined : json['id'], + 'lastName': json['lastName'] == null ? undefined : json['lastName'], + 'username': json['username'] == null ? undefined : json['username'], + 'organizations': json['organizations'] == null ? undefined : json['organizations'], + }; +} + +export function UserWithOrgsRepresentationToJSON(json: any): UserWithOrgsRepresentation { + return UserWithOrgsRepresentationToJSONTyped(json, false); +} + +export function UserWithOrgsRepresentationToJSONTyped(value?: UserWithOrgsRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'attributes': value['attributes'], + 'createdTimestamp': value['createdTimestamp'], + 'email': value['email'], + 'emailVerified': value['emailVerified'], + 'enabled': value['enabled'], + 'firstName': value['firstName'], + 'groups': value['groups'], + 'id': value['id'], + 'lastName': value['lastName'], + 'username': value['username'], + 'organizations': value['organizations'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/WebhookRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/WebhookRepresentation.ts index cdb0681..cf11319 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/WebhookRepresentation.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/WebhookRepresentation.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -21,56 +21,38 @@ import { mapValues } from '../runtime'; export interface WebhookRepresentation { /** * - * @type {object} - * @memberof WebhookRepresentation */ attributes?: object; /** * - * @type {string} - * @memberof WebhookRepresentation */ id?: string; /** * - * @type {boolean} - * @memberof WebhookRepresentation */ enabled?: boolean; /** * - * @type {string} - * @memberof WebhookRepresentation */ url?: string; /** * - * @type {string} - * @memberof WebhookRepresentation */ secret?: string; /** * - * @type {string} - * @memberof WebhookRepresentation */ createdBy?: string; /** * - * @type {string} - * @memberof WebhookRepresentation */ - createdAt?: string; + createdAt?: number; /** * - * @type {string} - * @memberof WebhookRepresentation */ realm?: string; /** * - * @type {Array} - * @memberof WebhookRepresentation */ eventTypes?: Array; } @@ -104,11 +86,11 @@ export function WebhookRepresentationFromJSONTyped(json: any, ignoreDiscriminato }; } - export function WebhookRepresentationToJSON(json: any): WebhookRepresentation { - return WebhookRepresentationToJSONTyped(json, false); - } +export function WebhookRepresentationToJSON(json: any): WebhookRepresentation { + return WebhookRepresentationToJSONTyped(json, false); +} - export function WebhookRepresentationToJSONTyped(value?: WebhookRepresentation | null, ignoreDiscriminator: boolean = false): any { +export function WebhookRepresentationToJSONTyped(value?: WebhookRepresentation | null, ignoreDiscriminator: boolean = false): any { if (value == null) { return value; } diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/WebhookSendRepresentation.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/WebhookSendRepresentation.ts new file mode 100644 index 0000000..a0c9a04 --- /dev/null +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/WebhookSendRepresentation.ts @@ -0,0 +1,131 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * Phase Two Admin REST API + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * + * The version of the OpenAPI document: v1 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + +import { mapValues } from '../runtime'; +import type { WebhookRepresentation } from './WebhookRepresentation'; +import { + WebhookRepresentationFromJSON, + WebhookRepresentationFromJSONTyped, + WebhookRepresentationToJSON, + WebhookRepresentationToJSONTyped, +} from './WebhookRepresentation'; + +/** + * + * @export + * @interface WebhookSendRepresentation + */ +export interface WebhookSendRepresentation { + /** + * + */ + id?: string; + /** + * + */ + type?: string; + /** + * + */ + status?: number; + /** + * + */ + statusMessage?: string; + /** + * + */ + retried?: number; + /** + * + */ + sentAt?: string; + /** + * + */ + eventId?: string; + /** + * + */ + keycloakEventType?: string; + /** + * + */ + keycloakEventId?: string; + /** + * + */ + webhook?: WebhookRepresentation; + /** + * + */ + payload?: string; +} + +/** + * Check if a given object implements the WebhookSendRepresentation interface. + */ +export function instanceOfWebhookSendRepresentation(value: object): value is WebhookSendRepresentation { + return true; +} + +export function WebhookSendRepresentationFromJSON(json: any): WebhookSendRepresentation { + return WebhookSendRepresentationFromJSONTyped(json, false); +} + +export function WebhookSendRepresentationFromJSONTyped(json: any, ignoreDiscriminator: boolean): WebhookSendRepresentation { + if (json == null) { + return json; + } + return { + + 'id': json['id'] == null ? undefined : json['id'], + 'type': json['type'] == null ? undefined : json['type'], + 'status': json['status'] == null ? undefined : json['status'], + 'statusMessage': json['status_message'] == null ? undefined : json['status_message'], + 'retried': json['retried'] == null ? undefined : json['retried'], + 'sentAt': json['sent_at'] == null ? undefined : json['sent_at'], + 'eventId': json['event_id'] == null ? undefined : json['event_id'], + 'keycloakEventType': json['keycloak_event_type'] == null ? undefined : json['keycloak_event_type'], + 'keycloakEventId': json['keycloak_event_id'] == null ? undefined : json['keycloak_event_id'], + 'webhook': json['webhook'] == null ? undefined : WebhookRepresentationFromJSON(json['webhook']), + 'payload': json['payload'] == null ? undefined : json['payload'], + }; +} + +export function WebhookSendRepresentationToJSON(json: any): WebhookSendRepresentation { + return WebhookSendRepresentationToJSONTyped(json, false); +} + +export function WebhookSendRepresentationToJSONTyped(value?: WebhookSendRepresentation | null, ignoreDiscriminator: boolean = false): any { + if (value == null) { + return value; + } + + return { + + 'id': value['id'], + 'type': value['type'], + 'status': value['status'], + 'status_message': value['statusMessage'], + 'retried': value['retried'], + 'sent_at': value['sentAt'], + 'event_id': value['eventId'], + 'keycloak_event_type': value['keycloakEventType'], + 'keycloak_event_id': value['keycloakEventId'], + 'webhook': WebhookRepresentationToJSON(value['webhook']), + 'payload': value['payload'], + }; +} + diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/models/index.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/models/index.ts index 94fbc76..f207835 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/models/index.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/models/index.ts @@ -1,17 +1,44 @@ /* tslint:disable */ /* eslint-disable */ +export * from './AccessTokenResponse'; export * from './AuthDetailsRepresentation'; +export * from './BulkResponseItem'; +export * from './CreatePortalLinkForm'; +export * from './CredentialRepresentation'; export * from './EventRepresentation'; +export * from './ExternalBasicScimAuth'; +export * from './ExternalJwtScimAuth'; +export * from './ExternalSecretScimAuth'; export * from './IdentityProviderMapperRepresentation'; export * from './IdentityProviderRepresentation'; +export * from './ImportOrganizationsForm'; export * from './InvitationRepresentation'; export * from './InvitationRequestRepresentation'; -export * from './MagicLinkRepresentation'; +export * from './KeycloakScimAuth'; +export * from './LinkIdentityProviderRepresentation'; +export * from './MagicLinkRequest'; +export * from './MagicLinkResponse'; export * from './MyOrganizationRepresentation'; +export * from './OrganizationConfigRepresentation'; export * from './OrganizationDomainRepresentation'; +export * from './OrganizationExportRepresentation'; +export * from './OrganizationExportRepresentationAllOfMembers'; +export * from './OrganizationMemberAttributeRepresentation'; export * from './OrganizationRepresentation'; export * from './OrganizationRoleRepresentation'; +export * from './OrganizationScimAuth'; +export * from './OrganizationScimRepresentation'; +export * from './OrganizationsConfigRepresentation'; +export * from './OrganizationsExportRepresentation'; +export * from './OrganizationsImportRepresentation'; +export * from './OrganizationsImportResultRepresentation'; +export * from './OrganizationsImportResultRepresentationErrorsInner'; export * from './PortalLinkRepresentation'; export * from './RealmAttributeRepresentation'; +export * from './SwitchOrganizationRepresentation'; +export * from './UserBriefRepresentation'; export * from './UserRepresentation'; +export * from './UserWithOrgsBriefRepresentation'; +export * from './UserWithOrgsRepresentation'; export * from './WebhookRepresentation'; +export * from './WebhookSendRepresentation'; diff --git a/multitenant/libs/phasetwo-orgs-api/src/lib/runtime.ts b/multitenant/libs/phasetwo-orgs-api/src/lib/runtime.ts index 577c138..7a894bc 100644 --- a/multitenant/libs/phasetwo-orgs-api/src/lib/runtime.ts +++ b/multitenant/libs/phasetwo-orgs-api/src/lib/runtime.ts @@ -2,7 +2,7 @@ /* eslint-disable */ /** * Phase Two Admin REST API - * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/17.0/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak-nodejs-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/master/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | + * This is a REST API reference for the Phase Two Keycloak custom resources. These are extensions to the standard [Keycloak Admin REST API](https://www.keycloak.org/docs-api/latest/rest-api/index.html). ### Base URI format Paths specified in the documentation are relative to the the base URI. - Format: `https://:/auth/realms` - Example: `https://app.phasetwo.io/auth/realms` ### Authentication Authentication is achieved by using the `Authentication: Bearer ` header in all requests. This is either the access token received from a normal authentication, or by a request directly to the OpenID Connect token endpoint. It is recommended that you use a Keycloak Admin Client, such as [this one for Javascript](https://github.com/keycloak/keycloak/tree/main/js/libs/keycloak-admin-client), as they take care of authentication, getting an access token, and refreshing it when it expires. #### Client credentials grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=client_credentials&client_id=admin-cli&client_secret=fd649804-3a74-4d69-acaa-8f065c6b7da1 ``` #### Password grant example ``` POST /auth/realms/test-realm/protocol/openid-connect/token Host: app.phasetwo.io Accept: application/json Content-type: application/x-www-form-urlencoded grant_type=password&username=uname@foo.com&password=pwd123AZY&client_id=admin-cli ``` ### SDKs Modern API libraries are available for several common languages. These are available as open source at the links below, or you can choose to generate your own using our [OpenAPI spec file](https://raw.githubusercontent.com/p2-inc/phasetwo-docs/main/openapi.yaml). | Language | Library | | --- | --- | | Java (and other JVM langs) | https://github.com/p2-inc/phasetwo-java | | JavaScript/TypeScript | https://github.com/p2-inc/phasetwo-js | | Python | https://github.com/p2-inc/phasetwo-python | * * The version of the OpenAPI document: v1 * @@ -12,7 +12,6 @@ * Do not edit the class manually. */ - export const BASE_PATH = "https://app.phasetwo.io/realms".replace(/\/+$/, ""); export interface ConfigurationParameters { @@ -91,7 +90,7 @@ export const DefaultConfig = new Configuration(); */ export class BaseAPI { - private static readonly jsonRegex = new RegExp('^(:?application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(:?;.*)?$', 'i'); + private static readonly jsonRegex = /^(:?application\/json|[^;/ \t]+\/[^;/ \t]+[+]json)[ \t]*(:?;.*)?$/i; private middleware: Middleware[]; constructor(protected configuration = DefaultConfig) { @@ -261,6 +260,12 @@ export class ResponseError extends Error { override name: "ResponseError" = "ResponseError"; constructor(public response: Response, msg?: string) { super(msg); + + // restore prototype chain + const actualProto = new.target.prototype; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(this, actualProto); + } } } @@ -268,6 +273,12 @@ export class FetchError extends Error { override name: "FetchError" = "FetchError"; constructor(public cause: Error, msg?: string) { super(msg); + + // restore prototype chain + const actualProto = new.target.prototype; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(this, actualProto); + } } } @@ -275,6 +286,12 @@ export class RequiredError extends Error { override name: "RequiredError" = "RequiredError"; constructor(public field: string, msg?: string) { super(msg); + + // restore prototype chain + const actualProto = new.target.prototype; + if (Object.setPrototypeOf) { + Object.setPrototypeOf(this, actualProto); + } } } @@ -329,7 +346,7 @@ function querystringSingleKey(key: string, value: string | number | null | undef return querystringSingleKey(key, valueAsArray, keyPrefix); } if (value instanceof Date) { - return `${encodeURIComponent(fullKey)}=${encodeURIComponent(value.toISOString())}`; + return `${encodeURIComponent(fullKey)}=${encodeURIComponent(serializeDateTime(value))}`; } if (value instanceof Object) { return querystring(value as HTTPQuery, fullKey); @@ -337,16 +354,78 @@ function querystringSingleKey(key: string, value: string | number | null | undef return `${encodeURIComponent(fullKey)}=${encodeURIComponent(String(value))}`; } +export function exists(json: any, key: string) { + const value = json[key]; + return value !== null && value !== undefined; +} + +/** + * Every generated date call site routes through these. + * + * `format: date` is a calendar date, with no time and no offset, so it is converted + * against the local calendar on both ends: they have to agree or the date shifts by + * a day. `format: date-time` is an instant and uses UTC. + */ +export function serializeDateTime(value: Date): string { + return value.toISOString(); +} + +export function serializeDate(value: Date): string { + if (isNaN(value.getTime())) { + throw new RangeError('Invalid time value'); + } + const year = ('000' + value.getFullYear()).slice(-4); + const month = ('0' + (value.getMonth() + 1)).slice(-2); + const day = ('0' + value.getDate()).slice(-2); + return `${year}-${month}-${day}`; +} + + +export function parseDate(value: Date | string): Date { + if (value instanceof Date) { + return value; + } + // `new Date("2026-08-05")` would parse as UTC midnight: a different day west of UTC. + // Local midnight is the stated day everywhere. setFullYear avoids the 1900 offset the + // multi-argument constructor applies to years 0-99. + const fullDate = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(value)); + if (fullDate) { + const year = Number(fullDate[1]); + const month = Number(fullDate[2]) - 1; + const day = Number(fullDate[3]); + const date = new Date(0); + date.setFullYear(year, month, day); + date.setHours(0, 0, 0, 0); + // Out-of-range components (or a day the local zone skipped) silently roll over, + // which would hand back a date the server never sent. + if (date.getFullYear() !== year || date.getMonth() !== month || date.getDate() !== day) { + return new Date(NaN); + } + return date; + } + return new Date(value); +} + +export function parseDateTime(value: any): Date { + return new Date(value); +} + export function mapValues(data: any, fn: (item: any) => any) { - return Object.keys(data).reduce( - (acc, key) => ({ ...acc, [key]: fn(data[key]) }), - {} - ); + const result: { [key: string]: any } = {}; + for (const key of Object.keys(data)) { + result[key] = fn(data[key]); + } + return result; +} + +// Pass-through serializer for `any`-typed properties in form data. See #1877. +export function anyToJSON(value: any): any { + return value; } export function canConsumeForm(consumes: Consume[]): boolean { for (const consume of consumes) { - if ('multipart/form-data' === consume.contentType) { + if (consume.contentType?.startsWith('multipart/form-data') == true) { return true; } } diff --git a/multitenant/libs/phasetwo-orgs-api/tsconfig.json b/multitenant/libs/phasetwo-orgs-api/tsconfig.json index 6f7169a..564a599 100644 --- a/multitenant/libs/phasetwo-orgs-api/tsconfig.json +++ b/multitenant/libs/phasetwo-orgs-api/tsconfig.json @@ -1,22 +1,4 @@ { "extends": "../../tsconfig.base.json", - "compilerOptions": { - "module": "commonjs", - "forceConsistentCasingInFileNames": true, - "strict": true, - "noImplicitOverride": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "noPropertyAccessFromIndexSignature": true - }, - "files": [], - "include": [], - "references": [ - { - "path": "./tsconfig.lib.json" - }, - { - "path": "./tsconfig.spec.json" - } - ] + "include": ["src"] } diff --git a/multitenant/libs/phasetwo-orgs-api/tsconfig.lib.json b/multitenant/libs/phasetwo-orgs-api/tsconfig.lib.json deleted file mode 100644 index 33eca2c..0000000 --- a/multitenant/libs/phasetwo-orgs-api/tsconfig.lib.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "declaration": true, - "types": ["node"] - }, - "include": ["src/**/*.ts"], - "exclude": ["jest.config.ts", "src/**/*.spec.ts", "src/**/*.test.ts"] -} diff --git a/multitenant/libs/phasetwo-orgs-api/tsconfig.spec.json b/multitenant/libs/phasetwo-orgs-api/tsconfig.spec.json deleted file mode 100644 index 9b2a121..0000000 --- a/multitenant/libs/phasetwo-orgs-api/tsconfig.spec.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "include": [ - "jest.config.ts", - "src/**/*.test.ts", - "src/**/*.spec.ts", - "src/**/*.d.ts" - ] -} diff --git a/multitenant/libs/ui-shared/.babelrc b/multitenant/libs/ui-shared/.babelrc deleted file mode 100644 index 1ea870e..0000000 --- a/multitenant/libs/ui-shared/.babelrc +++ /dev/null @@ -1,12 +0,0 @@ -{ - "presets": [ - [ - "@nx/react/babel", - { - "runtime": "automatic", - "useBuiltIns": "usage" - } - ] - ], - "plugins": [] -} diff --git a/multitenant/libs/ui-shared/README.md b/multitenant/libs/ui-shared/README.md index 1040caf..56baec6 100644 --- a/multitenant/libs/ui-shared/README.md +++ b/multitenant/libs/ui-shared/README.md @@ -1,7 +1,11 @@ # ui-shared -This library was generated with [Nx](https://nx.dev). +The page the Zoo and Aquarium apps share. It follows the look of the other Phase Two examples. -## Running unit tests +- `AppLayout`: the background picture, the Phase Two logo, a header with the React and GitHub icons (linking to this example on GitHub) and the app name, and the footer. +- `Organizations`: loads the logged-in user's organizations through [`api-manager`](../api-manager) and shows one card per organization with its roles. Each card says whether the organization gives access to the current app, that is whether the user has the app's role (`zoo` or `aquarium`) in it. +- `Button`, `FooterLinks` and the inline SVG icons. -Run `nx test ui-shared` to execute the unit tests via [Vitest](https://vitest.dev/). +Tailwind CSS only scans the Vite root, the app folder, for class names. The apps' stylesheets (`apps/*/src/styles.css`) add this folder with `@source`, so the classes used here end up in their CSS. + +Run its tests with `pnpm nx test ui-shared`. diff --git a/multitenant/libs/ui-shared/eslint.config.js b/multitenant/libs/ui-shared/eslint.config.js deleted file mode 100644 index 2f6e3f0..0000000 --- a/multitenant/libs/ui-shared/eslint.config.js +++ /dev/null @@ -1,12 +0,0 @@ -const nx = require('@nx/eslint-plugin'); -const baseConfig = require('../../eslint.config.js'); - -module.exports = [ - ...baseConfig, - ...nx.configs['flat/react'], - { - files: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'], - // Override or add rules here - rules: {}, - }, -]; diff --git a/multitenant/libs/ui-shared/eslint.config.mjs b/multitenant/libs/ui-shared/eslint.config.mjs new file mode 100644 index 0000000..2a7f6f1 --- /dev/null +++ b/multitenant/libs/ui-shared/eslint.config.mjs @@ -0,0 +1,4 @@ +import nx from '@nx/eslint-plugin'; +import baseConfig from '../../eslint.config.mjs'; + +export default [...baseConfig, ...nx.configs['flat/react']]; diff --git a/multitenant/libs/ui-shared/postcss.config.js b/multitenant/libs/ui-shared/postcss.config.js deleted file mode 100644 index c72626d..0000000 --- a/multitenant/libs/ui-shared/postcss.config.js +++ /dev/null @@ -1,15 +0,0 @@ -const { join } = require('path'); - -// Note: If you use library-specific PostCSS/Tailwind configuration then you should remove the `postcssConfig` build -// option from your application's configuration (i.e. project.json). -// -// See: https://nx.dev/guides/using-tailwind-css-in-react#step-4:-applying-configuration-to-libraries - -module.exports = { - plugins: { - tailwindcss: { - config: join(__dirname, 'tailwind.config.js'), - }, - autoprefixer: {}, - }, -}; diff --git a/multitenant/libs/ui-shared/project.json b/multitenant/libs/ui-shared/project.json index c946a36..9445422 100644 --- a/multitenant/libs/ui-shared/project.json +++ b/multitenant/libs/ui-shared/project.json @@ -3,7 +3,5 @@ "$schema": "../../node_modules/nx/schemas/project-schema.json", "sourceRoot": "libs/ui-shared/src", "projectType": "library", - "tags": [], - "// targets": "to see all targets run: nx show project ui-shared --web", - "targets": {} + "tags": [] } diff --git a/multitenant/libs/ui-shared/src/index.ts b/multitenant/libs/ui-shared/src/index.ts index 5df6184..a74ed26 100644 --- a/multitenant/libs/ui-shared/src/index.ts +++ b/multitenant/libs/ui-shared/src/index.ts @@ -1,3 +1,4 @@ export * from './lib/app-layout'; +export * from './lib/button'; export * from './lib/footer-links'; export * from './lib/orgs'; diff --git a/multitenant/libs/ui-shared/src/lib/app-layout.tsx b/multitenant/libs/ui-shared/src/lib/app-layout.tsx index a43bb16..d68a424 100644 --- a/multitenant/libs/ui-shared/src/lib/app-layout.tsx +++ b/multitenant/libs/ui-shared/src/lib/app-layout.tsx @@ -1,63 +1,59 @@ -import { Icon } from '@iconify/react'; -import { FooterLinks } from './footer-links'; - +import type { ReactNode } from 'react'; import homeBgMobile from '../assets/home-bg-mobile.webp'; import homeBg from '../assets/home-bg.webp'; -import Logo from '../assets/logo_phase_slash.svg'; +import logo from '../assets/logo_phase_slash.svg'; +import { FooterLinks } from './footer-links'; +import { GithubIcon, ReactIcon } from './icons'; + +const exampleUrl = 'https://github.com/p2-inc/examples/tree/main/multitenant'; export function AppLayout({ - Auth, appName, - appTenant, + children, }: { - Auth: React.ComponentType; appName: string; - appTenant: string; + children: ReactNode; }) { return ( -
+
- Gradient Background + -
+
Phase Two -

- - -

+ +
-
-
Application: {appName}
-
Tenant: {appTenant}
-
+

+ {appName} +

+

+ Multitenant Β· React Β· oidc-spa +

-
-
-
- + +
+
+ {children}
-
+
); } - -export default AppLayout; diff --git a/multitenant/libs/ui-shared/src/lib/button.tsx b/multitenant/libs/ui-shared/src/lib/button.tsx new file mode 100644 index 0000000..cbe20da --- /dev/null +++ b/multitenant/libs/ui-shared/src/lib/button.tsx @@ -0,0 +1,11 @@ +import type { ButtonHTMLAttributes } from 'react'; + +export function Button(props: ButtonHTMLAttributes) { + return ( +