From 7b7c28a59cf632a4130e47dce9cf96e5e6df48fc Mon Sep 17 00:00:00 2001 From: Yordis Prieto Date: Sun, 7 Apr 2024 03:56:46 -0400 Subject: [PATCH] refactor: zitadel server Signed-off-by: Yordis Prieto --- CONTRIBUTING.md | 2 +- README.md | 67 +++-- apps/login/app/(login)/accounts/page.tsx | 7 +- .../(login)/idp/[provider]/failure/page.tsx | 14 +- .../(login)/idp/[provider]/success/page.tsx | 7 +- apps/login/app/(login)/idp/page.tsx | 12 +- apps/login/app/(login)/loginname/page.tsx | 12 +- apps/login/app/(login)/passkey/add/page.tsx | 6 +- apps/login/app/(login)/passkey/login/page.tsx | 8 +- apps/login/app/(login)/password/page.tsx | 6 +- apps/login/app/(login)/register/page.tsx | 6 +- apps/login/app/(login)/signedin/page.tsx | 25 +- apps/login/app/(login)/verify/page.tsx | 4 +- apps/login/app/api/idp/start/route.ts | 17 +- apps/login/app/api/loginname/route.ts | 7 +- apps/login/app/api/passkeys/route.ts | 32 +- apps/login/app/api/passkeys/verify/route.ts | 22 +- apps/login/app/api/registeruser/route.ts | 9 +- apps/login/app/api/resendverifyemail/route.ts | 5 +- apps/login/app/api/session/route.ts | 7 +- apps/login/app/api/verifyemail/route.ts | 8 +- apps/login/app/layout.tsx | 5 - apps/login/app/login/route.ts | 23 +- apps/login/lib/zitadel.ts | 275 ++---------------- apps/login/ui/DynamicTheme.tsx | 2 +- apps/login/ui/PasswordComplexity.tsx | 2 +- apps/login/ui/PrivacyPolicyCheckboxes.tsx | 2 +- apps/login/ui/RegisterFormWithoutPassword.tsx | 2 +- apps/login/ui/RegisterPasskey.tsx | 2 +- apps/login/ui/SessionItem.tsx | 2 +- apps/login/ui/SessionsList.tsx | 2 +- apps/login/ui/SetPasswordForm.tsx | 2 +- apps/login/ui/ThemeWrapper.tsx | 2 +- apps/login/ui/UsernameForm.tsx | 2 +- apps/login/utils/colors.ts | 2 +- apps/login/utils/session.ts | 61 ++-- packages/zitadel-client/jest.config.ts | 10 +- .../zitadel-client/src/middleware.test.ts | 113 ++++--- packages/zitadel-next/jest.config.ts | 10 +- packages/zitadel-react/jest.config.ts | 12 +- packages/zitadel-server/buf.gen.yaml | 2 +- packages/zitadel-server/jest.config.ts | 10 +- packages/zitadel-server/package.json | 27 +- packages/zitadel-server/src/admin/admin.ts | 24 -- packages/zitadel-server/src/admin/index.ts | 1 - packages/zitadel-server/src/auth/auth.ts | 32 -- packages/zitadel-server/src/auth/index.ts | 2 - packages/zitadel-server/src/index.ts | 119 +------- packages/zitadel-server/src/internal.ts | 3 - .../zitadel-server/src/management/index.ts | 3 - .../src/management/management.ts | 45 --- .../zitadel-server/src/middleware.test.ts | 113 ++++--- packages/zitadel-server/src/middleware.ts | 16 +- packages/zitadel-server/src/server.ts | 88 ++---- packages/zitadel-server/src/system/index.ts | 1 - packages/zitadel-server/src/system/system.ts | 35 --- packages/zitadel-server/src/v1.ts | 32 ++ packages/zitadel-server/src/v2/oidc/index.ts | 2 - packages/zitadel-server/src/v2/oidc/oidc.ts | 24 -- .../zitadel-server/src/v2/session/index.ts | 2 - .../zitadel-server/src/v2/session/session.ts | 28 -- .../zitadel-server/src/v2/settings/index.ts | 2 - .../src/v2/settings/settings.ts | 28 -- packages/zitadel-server/src/v2/user/index.ts | 2 - packages/zitadel-server/src/v2/user/user.ts | 28 -- packages/zitadel-server/src/v2beta.ts | 61 ++++ packages/zitadel-server/src/v3alpha.ts | 22 ++ packages/zitadel-server/tsup.config.ts | 6 +- 68 files changed, 541 insertions(+), 1031 deletions(-) delete mode 100644 packages/zitadel-server/src/admin/admin.ts delete mode 100644 packages/zitadel-server/src/admin/index.ts delete mode 100644 packages/zitadel-server/src/auth/auth.ts delete mode 100644 packages/zitadel-server/src/auth/index.ts delete mode 100644 packages/zitadel-server/src/internal.ts delete mode 100644 packages/zitadel-server/src/management/index.ts delete mode 100644 packages/zitadel-server/src/management/management.ts delete mode 100644 packages/zitadel-server/src/system/index.ts delete mode 100644 packages/zitadel-server/src/system/system.ts create mode 100644 packages/zitadel-server/src/v1.ts delete mode 100644 packages/zitadel-server/src/v2/oidc/index.ts delete mode 100644 packages/zitadel-server/src/v2/oidc/oidc.ts delete mode 100644 packages/zitadel-server/src/v2/session/index.ts delete mode 100644 packages/zitadel-server/src/v2/session/session.ts delete mode 100644 packages/zitadel-server/src/v2/settings/index.ts delete mode 100644 packages/zitadel-server/src/v2/settings/settings.ts delete mode 100644 packages/zitadel-server/src/v2/user/index.ts delete mode 100644 packages/zitadel-server/src/v2/user/user.ts create mode 100644 packages/zitadel-server/src/v2beta.ts create mode 100644 packages/zitadel-server/src/v3alpha.ts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 44e0914bd..18038ed32 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -57,6 +57,7 @@ export $(cat ./apps/login/.env.acceptance | xargs) ### Developing Against Your ZITADEL Cloud Instance Configure your shell by exporting the following environment variables: + ```sh export ZITADEL_API_URL= export ZITADEL_ORG_ID= @@ -93,5 +94,4 @@ In apps/login, these commands also spin up the application and a ZITADEL gRPC AP If you want to run the integration tests standalone against an environment of your choice, navigate to ./apps/login, [configure your shell as you like](# Developing Against Your ZITADEL Cloud Instance) and run `pnpm test:integration:run` or `pnpm test:integration:open`. Then you need to lifecycle the mock process using the command `pnpm mock` or the more fine grained commands `pnpm mock:build`, `pnpm mock:build:nocache`, `pnpm mock:run` and `pnpm mock:destroy`. - That's it! 🎉 diff --git a/README.md b/README.md index 9a3203742..c8b5fa0cd 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,17 @@ # ZITADEL typescript with Turborepo and Changesets -This repository contains all TypeScript and JavaScript packages and applications you need to create your own ZITADEL Login UI. -The repo makes use of the [build system Turbo](https://turbo.build/repo) and the [Changesets CLI for versioning the packages](https://github.com/changesets/changesets). +This repository contains all TypeScript and JavaScript packages and applications you need to create your own ZITADEL +Login UI. +The repo makes use of the [build system Turbo](https://turbo.build/repo) and +the [Changesets CLI for versioning the packages](https://github.com/changesets/changesets). **⚠️ This repo and packages are in alpha state and subject to change ⚠️** The scope of functionality of this repo and packages is limited and under active development. Once the package structure is set and all APIs are fully implemented we'll move this repo to beta state. You can read the [contribution guide](/CONTRIBUTING.md) on how to contribute. -Questions can be raised in our [Discord channel](https://discord.gg/erh5Brh7jE) or as a [GitHub issue](https://github.com/zitadel/typescript/issues). +Questions can be raised in our [Discord channel](https://discord.gg/erh5Brh7jE) or as +a [GitHub issue](https://github.com/zitadel/typescript/issues). ## Developing Your Own ZITADEL Login UI @@ -36,16 +39,18 @@ Each package and app is 100% [TypeScript](https://www.typescriptlang.org/). ### Login -The login is currently in a work in progress state. -The goal is to implement a login UI, using the session API of ZITADEL, which also implements the OIDC Standard and is ready to use for everyone. +The login is currently in a work in progress state. +The goal is to implement a login UI, using the session API of ZITADEL, which also implements the OIDC Standard and is +ready to use for everyone. -In the first phase we want to have a MVP login ready with the OIDC Standard and a basic feature set. In a second step the features will be extended. +In the first phase we want to have a MVP login ready with the OIDC Standard and a basic feature set. In a second step +the features will be extended. This list should show the current implementation state, and also what is missing. You can already use the current state, and extend it with your needs. - [x] Local User Registration (with Password) -- [ ] User Registration and Login with external Provider +- [ ] User Registration and Login with external Provider - [ ] Google - [ ] GitHub - [ ] GitHub Enterprise @@ -67,21 +72,21 @@ You can already use the current state, and extend it with your needs. - [ ] Domain Discovery - [ ] Branding - OIDC Standard - - [ ] Authorization Code Flow with PKCE - - [ ] AuthRequest `hintUserId` - - [ ] AuthRequest `loginHint` - - [ ] AuthRequest `prompt` - - [x] Login - - [x] Select Account - - [ ] Consent - - [ ] Create - - Scopes - - [ ] `openid email profile address`` - - [ ] `offline access` - - [ ] `urn:zitadel:iam:org:idp:id:{idp_id}` - - [ ] `urn:zitadel:iam:org:project:id:zitadel:aud` - - [ ] `urn:zitadel:iam:org:id:{orgid}` - - [ ] AuthRequest UI locales + - [ ] Authorization Code Flow with PKCE + - [ ] AuthRequest `hintUserId` + - [ ] AuthRequest `loginHint` + - [ ] AuthRequest `prompt` + - [x] Login + - [x] Select Account + - [ ] Consent + - [ ] Create + - Scopes + - [ ] `openid email profile address`` + - [ ] `offline access` + - [ ] `urn:zitadel:iam:org:idp:id:{idp_id}` + - [ ] `urn:zitadel:iam:org:project:id:zitadel:aud` + - [ ] `urn:zitadel:iam:org:id:{orgid}` + - [ ] AuthRequest UI locales ## Tooling @@ -103,11 +108,14 @@ You can already use the current state, and extend it with your needs. ## Versioning And Publishing Packages Package publishing has been configured using [Changesets](https://github.com/changesets/changesets). -Here is their [documentation](https://github.com/changesets/changesets#documentation) for more information about the workflow. +Here is their [documentation](https://github.com/changesets/changesets#documentation) for more information about the +workflow. -The [GitHub Action](https://github.com/changesets/action) needs an `NPM_TOKEN` and `GITHUB_TOKEN` in the repository settings. The [Changesets bot](https://github.com/apps/changeset-bot) should also be installed on the GitHub repository. +The [GitHub Action](https://github.com/changesets/action) needs an `NPM_TOKEN` and `GITHUB_TOKEN` in the repository +settings. The [Changesets bot](https://github.com/apps/changeset-bot) should also be installed on the GitHub repository. -Read the [changesets documentation](https://github.com/changesets/changesets/blob/main/docs/automating-changesets.md) for more information about this automation +Read the [changesets documentation](https://github.com/changesets/changesets/blob/main/docs/automating-changesets.md) +for more information about this automation ### NPM @@ -134,8 +142,10 @@ pnpm install ``` then setup the environment for the login application which needs a `.env.local` in `/apps/login`. -Go to your instance and create a service user for the application having the IAM_OWNER manager role. -This user is required to have access to create users on your primary organization and reading policy data so it can be restricted to your personal use case but we'll stick with IAM_OWNER for convenience. Create a PAT and copy the value to paste it under the `ZITADEL_SERVICE_USER_TOKEN` key. +Go to your instance and create a service user for the application having the `IAM_OWNER` manager role. +This user is required to have access to create users on your primary organization and reading policy data so it can be +restricted to your personal use case but we'll stick with `IAM_OWNER` for convenience. Create a PAT and copy the value to +paste it under the `ZITADEL_SERVICE_USER_TOKEN` key. The file should look as follows: ``` @@ -162,7 +172,8 @@ Open the login application with your favorite browser at `localhost:3000`. To deploy your own version on Vercel, navigate to your instance and create a service user. Copy its id from the overview and set it as ZITADEL_SERVICE_USER_ID. -Then create a personal access token (PAT), copy and set it as ZITADEL_SERVICE_USER_TOKEN, then navigate to your instance settings and make sure it gets IAM_OWNER permissions. +Then create a personal access token (PAT), copy and set it as ZITADEL_SERVICE_USER_TOKEN, then navigate to your instance +settings and make sure it gets IAM_OWNER permissions. Finally set your instance url as ZITADEL_API_URL. Make sure to set it without trailing slash. [![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fzitadel%2Ftypescript&env=ZITADEL_API_URL,ZITADEL_SERVICE_USER_ID,ZITADEL_SERVICE_USER_TOKEN&root-directory=apps/login&envDescription=Setup%20a%20service%20account%20with%20IAM_OWNER%20membership%20on%20your%20instance%20and%20provide%20its%20id%20and%20personal%20access%20token.&project-name=zitadel-login&repository-name=zitadel-login) diff --git a/apps/login/app/(login)/accounts/page.tsx b/apps/login/app/(login)/accounts/page.tsx index 6985ea67f..467752d6c 100644 --- a/apps/login/app/(login)/accounts/page.tsx +++ b/apps/login/app/(login)/accounts/page.tsx @@ -1,5 +1,5 @@ -import { Session } from "@zitadel/server"; -import { getBrandingSettings, listSessions, server } from "#/lib/zitadel"; +import { Session } from "@zitadel/server/v2beta"; +import { getBrandingSettings, listSessions } from "#/lib/zitadel"; import { getAllSessionCookieIds } from "#/utils/cookies"; import { UserPlusIcon } from "@heroicons/react/24/outline"; import Link from "next/link"; @@ -11,7 +11,6 @@ async function loadSessions(): Promise { if (ids && ids.length) { const response = await listSessions( - server, ids.filter((id: string | undefined) => !!id) ); return response?.sessions ?? []; @@ -31,7 +30,7 @@ export default async function Page({ let sessions = await loadSessions(); - const branding = await getBrandingSettings(server, organization); + const branding = await getBrandingSettings(organization); return ( diff --git a/apps/login/app/(login)/idp/[provider]/failure/page.tsx b/apps/login/app/(login)/idp/[provider]/failure/page.tsx index aada1c524..587d71c93 100644 --- a/apps/login/app/(login)/idp/[provider]/failure/page.tsx +++ b/apps/login/app/(login)/idp/[provider]/failure/page.tsx @@ -1,16 +1,6 @@ import { ProviderSlug } from "#/lib/demos"; -import { getBrandingSettings, server } from "#/lib/zitadel"; -import Alert, { AlertType } from "#/ui/Alert"; +import { getBrandingSettings } from "#/lib/zitadel"; import DynamicTheme from "#/ui/DynamicTheme"; -import IdpSignin from "#/ui/IdpSignin"; -import { - AddHumanUserRequest, - IDPInformation, - RetrieveIdentityProviderIntentResponse, - user, - IDPLink, -} from "@zitadel/server"; -import { ClientError } from "nice-grpc"; const PROVIDER_NAME_MAPPING: { [provider: string]: string; @@ -29,7 +19,7 @@ export default async function Page({ const { id, token, authRequestId, organization } = searchParams; const { provider } = params; - const branding = await getBrandingSettings(server, organization); + const branding = await getBrandingSettings(organization); if (provider) { return ( diff --git a/apps/login/app/(login)/idp/[provider]/success/page.tsx b/apps/login/app/(login)/idp/[provider]/success/page.tsx index 6aae35bf6..e08446ffa 100644 --- a/apps/login/app/(login)/idp/[provider]/success/page.tsx +++ b/apps/login/app/(login)/idp/[provider]/success/page.tsx @@ -1,5 +1,5 @@ import { ProviderSlug } from "#/lib/demos"; -import { getBrandingSettings, server } from "#/lib/zitadel"; +import { getBrandingSettings, userService } from "#/lib/zitadel"; import Alert, { AlertType } from "#/ui/Alert"; import DynamicTheme from "#/ui/DynamicTheme"; import IdpSignin from "#/ui/IdpSignin"; @@ -7,7 +7,6 @@ import { AddHumanUserRequest, IDPInformation, RetrieveIdentityProviderIntentResponse, - user, IDPLink, } from "@zitadel/server"; import { ClientError } from "nice-grpc"; @@ -65,7 +64,6 @@ function retrieveIDPIntent( id: string, token: string ): Promise { - const userService = user.getUser(server); return userService.retrieveIdentityProviderIntent( { idpIntentId: id, idpIntentToken: token }, {} @@ -77,7 +75,6 @@ function createUser( info: IDPInformation ): Promise { const userData = PROVIDER_MAPPING[provider](info); - const userService = user.getUser(server); return userService.addHumanUser(userData, {}).then((resp) => resp.userId); } @@ -91,7 +88,7 @@ export default async function Page({ const { id, token, authRequestId, organization } = searchParams; const { provider } = params; - const branding = await getBrandingSettings(server, organization); + const branding = await getBrandingSettings(organization); if (provider && id && token) { return retrieveIDPIntent(id, token) diff --git a/apps/login/app/(login)/idp/page.tsx b/apps/login/app/(login)/idp/page.tsx index c1da21788..6420483c4 100644 --- a/apps/login/app/(login)/idp/page.tsx +++ b/apps/login/app/(login)/idp/page.tsx @@ -1,22 +1,18 @@ import { getBrandingSettings, getLegalAndSupportSettings, - server, + settingsService, } from "#/lib/zitadel"; import DynamicTheme from "#/ui/DynamicTheme"; import { SignInWithIDP } from "#/ui/SignInWithIDP"; import { GetActiveIdentityProvidersResponse, IdentityProvider, - ZitadelServer, - settings, } from "@zitadel/server"; function getIdentityProviders( - server: ZitadelServer, orgId?: string ): Promise { - const settingsService = settings.getSettings(server); return settingsService .getActiveIdentityProviders( orgId ? { ctx: { orgId } } : { ctx: { instance: true } }, @@ -35,15 +31,15 @@ export default async function Page({ const authRequestId = searchParams?.authRequestId; const organization = searchParams?.organization; - const legal = await getLegalAndSupportSettings(server, organization); + const legal = await getLegalAndSupportSettings(organization); - const identityProviders = await getIdentityProviders(server, organization); + const identityProviders = await getIdentityProviders(organization); const host = process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : "http://localhost:3000"; - const branding = await getBrandingSettings(server, organization); + const branding = await getBrandingSettings(organization); return ( diff --git a/apps/login/app/(login)/loginname/page.tsx b/apps/login/app/(login)/loginname/page.tsx index b85a8a09f..88b1102e9 100644 --- a/apps/login/app/(login)/loginname/page.tsx +++ b/apps/login/app/(login)/loginname/page.tsx @@ -2,7 +2,7 @@ import { getBrandingSettings, getLegalAndSupportSettings, getLoginSettings, - server, + settingsService, } from "#/lib/zitadel"; import DynamicTheme from "#/ui/DynamicTheme"; import { SignInWithIDP } from "#/ui/SignInWithIDP"; @@ -11,14 +11,12 @@ import { GetActiveIdentityProvidersResponse, IdentityProvider, ZitadelServer, - settings, } from "@zitadel/server"; function getIdentityProviders( server: ZitadelServer, orgId?: string ): Promise { - const settingsService = settings.getSettings(server); return settingsService .getActiveIdentityProviders( orgId ? { ctx: { orgId } } : { ctx: { instance: true } }, @@ -39,16 +37,16 @@ export default async function Page({ const organization = searchParams?.organization; const submit: boolean = searchParams?.submit === "true"; - const loginSettings = await getLoginSettings(server, organization); - const legal = await getLegalAndSupportSettings(server); + const loginSettings = await getLoginSettings(organization); + const legal = await getLegalAndSupportSettings(); - const identityProviders = await getIdentityProviders(server, organization); + const identityProviders = await getIdentityProviders(organization); const host = process.env.VERCEL_URL ? `https://${process.env.VERCEL_URL}` : "http://localhost:3000"; - const branding = await getBrandingSettings(server, organization); + const branding = await getBrandingSettings(organization); return ( diff --git a/apps/login/app/(login)/passkey/add/page.tsx b/apps/login/app/(login)/passkey/add/page.tsx index 839ac2225..16eea777d 100644 --- a/apps/login/app/(login)/passkey/add/page.tsx +++ b/apps/login/app/(login)/passkey/add/page.tsx @@ -1,4 +1,4 @@ -import { getBrandingSettings, getSession, server } from "#/lib/zitadel"; +import { getBrandingSettings, getSession } from "#/lib/zitadel"; import Alert, { AlertType } from "#/ui/Alert"; import DynamicTheme from "#/ui/DynamicTheme"; import RegisterPasskey from "#/ui/RegisterPasskey"; @@ -20,7 +20,7 @@ export default async function Page({ loginName, organization ); - return getSession(server, recent.id, recent.token).then((response) => { + return getSession(recent.id, recent.token).then((response) => { if (response?.session) { return response.session; } @@ -33,7 +33,7 @@ export default async function Page({ ? "When set up, you will be able to authenticate without a password." : "Your device will ask for your fingerprint, face, or screen lock"; - const branding = await getBrandingSettings(server, organization); + const branding = await getBrandingSettings(organization); return ( diff --git a/apps/login/app/(login)/passkey/login/page.tsx b/apps/login/app/(login)/passkey/login/page.tsx index bcc366465..31ce03fd9 100644 --- a/apps/login/app/(login)/passkey/login/page.tsx +++ b/apps/login/app/(login)/passkey/login/page.tsx @@ -1,4 +1,4 @@ -import { getBrandingSettings, getSession, server } from "#/lib/zitadel"; +import { getBrandingSettings, getSession } from "#/lib/zitadel"; import Alert from "#/ui/Alert"; import DynamicTheme from "#/ui/DynamicTheme"; import LoginPasskey from "#/ui/LoginPasskey"; @@ -32,7 +32,7 @@ export default async function Page({ loginName, organization ); - return getSession(server, recent.id, recent.token).then((response) => { + return getSession(recent.id, recent.token).then((response) => { if (response?.session) { return response.session; } @@ -41,14 +41,14 @@ export default async function Page({ async function loadSessionById(sessionId: string, organization?: string) { const recent = await getSessionCookieById(sessionId, organization); - return getSession(server, recent.id, recent.token).then((response) => { + return getSession(recent.id, recent.token).then((response) => { if (response?.session) { return response.session; } }); } - const branding = await getBrandingSettings(server, organization); + const branding = await getBrandingSettings(organization); return ( diff --git a/apps/login/app/(login)/password/page.tsx b/apps/login/app/(login)/password/page.tsx index 9e4825749..9bd17842c 100644 --- a/apps/login/app/(login)/password/page.tsx +++ b/apps/login/app/(login)/password/page.tsx @@ -1,4 +1,4 @@ -import { getBrandingSettings, getSession, server } from "#/lib/zitadel"; +import { getBrandingSettings, getSession } from "#/lib/zitadel"; import Alert from "#/ui/Alert"; import DynamicTheme from "#/ui/DynamicTheme"; import PasswordForm from "#/ui/PasswordForm"; @@ -20,14 +20,14 @@ export default async function Page({ organization ); - return getSession(server, recent.id, recent.token).then((response) => { + return getSession(recent.id, recent.token).then((response) => { if (response?.session) { return response.session; } }); } - const branding = await getBrandingSettings(server, organization); + const branding = await getBrandingSettings(organization); return ( diff --git a/apps/login/app/(login)/register/page.tsx b/apps/login/app/(login)/register/page.tsx index 506b9df07..671120755 100644 --- a/apps/login/app/(login)/register/page.tsx +++ b/apps/login/app/(login)/register/page.tsx @@ -2,7 +2,6 @@ import { getBrandingSettings, getLegalAndSupportSettings, getPasswordComplexitySettings, - server, } from "#/lib/zitadel"; import DynamicTheme from "#/ui/DynamicTheme"; import RegisterFormWithoutPassword from "#/ui/RegisterFormWithoutPassword"; @@ -18,13 +17,12 @@ export default async function Page({ const setPassword = !!(firstname && lastname && email); - const legal = await getLegalAndSupportSettings(server, organization); + const legal = await getLegalAndSupportSettings(organization); const passwordComplexitySettings = await getPasswordComplexitySettings( - server, organization ); - const branding = await getBrandingSettings(server, organization); + const branding = await getBrandingSettings(organization); return setPassword ? ( diff --git a/apps/login/app/(login)/signedin/page.tsx b/apps/login/app/(login)/signedin/page.tsx index 4ee30a6c8..6e80fa026 100644 --- a/apps/login/app/(login)/signedin/page.tsx +++ b/apps/login/app/(login)/signedin/page.tsx @@ -1,9 +1,4 @@ -import { - createCallback, - getBrandingSettings, - getSession, - server, -} from "#/lib/zitadel"; +import { getBrandingSettings, getSession, oidcService } from "#/lib/zitadel"; import DynamicTheme from "#/ui/DynamicTheme"; import UserAvatar from "#/ui/UserAvatar"; import { getMostRecentCookieWithLoginname } from "#/utils/cookies"; @@ -13,14 +8,16 @@ async function loadSession(loginName: string, authRequestId?: string) { const recent = await getMostRecentCookieWithLoginname(`${loginName}`); if (authRequestId) { - return createCallback(server, { - authRequestId, - session: { sessionId: recent.id, sessionToken: recent.token }, - }).then(({ callbackUrl }) => { - return redirect(callbackUrl); - }); + return oidcService + .createCallback({ + authRequestId, + session: { sessionId: recent.id, sessionToken: recent.token }, + }) + .then(({ callbackUrl }) => { + return redirect(callbackUrl); + }); } - return getSession(server, recent.id, recent.token).then((response) => { + return getSession(recent.id, recent.token).then((response) => { if (response?.session) { return response.session; } @@ -31,7 +28,7 @@ export default async function Page({ searchParams }: { searchParams: any }) { const { loginName, authRequestId, organization } = searchParams; const sessionFactors = await loadSession(loginName, authRequestId); - const branding = await getBrandingSettings(server, organization); + const branding = await getBrandingSettings(organization); return ( diff --git a/apps/login/app/(login)/verify/page.tsx b/apps/login/app/(login)/verify/page.tsx index 32be25309..702de73d4 100644 --- a/apps/login/app/(login)/verify/page.tsx +++ b/apps/login/app/(login)/verify/page.tsx @@ -1,4 +1,4 @@ -import { getBrandingSettings, server } from "#/lib/zitadel"; +import { getBrandingSettings } from "#/lib/zitadel"; import DynamicTheme from "#/ui/DynamicTheme"; import VerifyEmailForm from "#/ui/VerifyEmailForm"; import { ExclamationTriangleIcon } from "@heroicons/react/24/outline"; @@ -15,7 +15,7 @@ export default async function Page({ searchParams }: { searchParams: any }) { passwordset, } = searchParams; - const branding = await getBrandingSettings(server, organization); + const branding = await getBrandingSettings(organization); return ( diff --git a/apps/login/app/api/idp/start/route.ts b/apps/login/app/api/idp/start/route.ts index 18a7f61e3..d0efc2493 100644 --- a/apps/login/app/api/idp/start/route.ts +++ b/apps/login/app/api/idp/start/route.ts @@ -1,4 +1,4 @@ -import { server, startIdentityProviderFlow } from "#/lib/zitadel"; +import { userService } from "#/lib/zitadel"; import { NextRequest, NextResponse } from "next/server"; export async function POST(request: NextRequest) { @@ -6,13 +6,14 @@ export async function POST(request: NextRequest) { if (body) { let { idpId, successUrl, failureUrl } = body; - return startIdentityProviderFlow(server, { - idpId, - urls: { - successUrl, - failureUrl, - }, - }) + return userService + .startIdentityProviderFlow({ + idpId, + urls: { + successUrl, + failureUrl, + }, + }) .then((resp) => { return NextResponse.json(resp); }) diff --git a/apps/login/app/api/loginname/route.ts b/apps/login/app/api/loginname/route.ts index 8b559e1f6..d4697ac05 100644 --- a/apps/login/app/api/loginname/route.ts +++ b/apps/login/app/api/loginname/route.ts @@ -1,4 +1,4 @@ -import { listAuthenticationMethodTypes, listUsers } from "#/lib/zitadel"; +import { listUsers, userService } from "#/lib/zitadel"; import { createSessionForUserIdAndUpdateCookie } from "#/utils/session"; import { NextRequest, NextResponse } from "next/server"; @@ -21,7 +21,10 @@ export async function POST(request: NextRequest) { ) .then((session) => { if (session.factors?.user?.id) { - return listAuthenticationMethodTypes(session.factors?.user?.id) + return userService + .listAuthenticationMethodTypes({ + userId: session.factors?.user?.id, + }) .then((methods) => { return NextResponse.json({ authMethodTypes: methods.authMethodTypes, diff --git a/apps/login/app/api/passkeys/route.ts b/apps/login/app/api/passkeys/route.ts index 559902621..4de07b889 100644 --- a/apps/login/app/api/passkeys/route.ts +++ b/apps/login/app/api/passkeys/route.ts @@ -1,9 +1,4 @@ -import { - createPasskeyRegistrationLink, - getSession, - registerPasskey, - server, -} from "#/lib/zitadel"; +import { getSession, userService } from "#/lib/zitadel"; import { getSessionCookieById } from "#/utils/cookies"; import { NextRequest, NextResponse } from "next/server"; @@ -14,11 +9,7 @@ export async function POST(request: NextRequest) { const sessionCookie = await getSessionCookieById(sessionId); - const session = await getSession( - server, - sessionCookie.id, - sessionCookie.token - ); + const session = await getSession(sessionCookie.id, sessionCookie.token); const domain: string = request.nextUrl.hostname; @@ -26,12 +17,23 @@ export async function POST(request: NextRequest) { if (userId) { // TODO: add org context - return createPasskeyRegistrationLink(userId) + return userService + .createPasskeyRegistrationLink({ + userId, + returnCode: {}, + }) .then((resp) => { const code = resp.code; - return registerPasskey(userId, code, domain).then((resp) => { - return NextResponse.json(resp); - }); + return userService + .registerPasskey({ + userId, + code, + domain, + // authenticator: + }) + .then((resp) => { + return NextResponse.json(resp); + }); }) .catch((error) => { console.error("error on creating passkey registration link"); diff --git a/apps/login/app/api/passkeys/verify/route.ts b/apps/login/app/api/passkeys/verify/route.ts index 1346ecc63..ea6db1b09 100644 --- a/apps/login/app/api/passkeys/verify/route.ts +++ b/apps/login/app/api/passkeys/verify/route.ts @@ -1,4 +1,4 @@ -import { getSession, server, verifyPasskeyRegistration } from "#/lib/zitadel"; +import { getSession, userService } from "#/lib/zitadel"; import { getSessionCookieById } from "#/utils/cookies"; import { NextRequest, NextResponse, userAgent } from "next/server"; @@ -15,22 +15,18 @@ export async function POST(request: NextRequest) { } const sessionCookie = await getSessionCookieById(sessionId); - const session = await getSession( - server, - sessionCookie.id, - sessionCookie.token - ); + const session = await getSession(sessionCookie.id, sessionCookie.token); const userId = session?.session?.factors?.user?.id; if (userId) { - return verifyPasskeyRegistration( - server, - passkeyId, - passkeyName, - publicKeyCredential, - userId - ) + return userService + .verifyPasskeyRegistration({ + passkeyId, + passkeyName, + publicKeyCredential, + userId, + }) .then((resp) => { return NextResponse.json(resp); }) diff --git a/apps/login/app/api/registeruser/route.ts b/apps/login/app/api/registeruser/route.ts index 575396143..7db1f9550 100644 --- a/apps/login/app/api/registeruser/route.ts +++ b/apps/login/app/api/registeruser/route.ts @@ -1,8 +1,5 @@ -import { addHumanUser, server } from "#/lib/zitadel"; -import { - createSessionAndUpdateCookie, - createSessionForUserIdAndUpdateCookie, -} from "#/utils/session"; +import { addHumanUser } from "#/lib/zitadel"; +import { createSessionForUserIdAndUpdateCookie } from "#/utils/session"; import { NextRequest, NextResponse } from "next/server"; export async function POST(request: NextRequest) { @@ -17,7 +14,7 @@ export async function POST(request: NextRequest) { authRequestId, } = body; - return addHumanUser(server, { + return addHumanUser({ email: email, firstName, lastName, diff --git a/apps/login/app/api/resendverifyemail/route.ts b/apps/login/app/api/resendverifyemail/route.ts index 15376ee76..ad95d4cd4 100644 --- a/apps/login/app/api/resendverifyemail/route.ts +++ b/apps/login/app/api/resendverifyemail/route.ts @@ -1,4 +1,4 @@ -import { setEmail, server } from "#/lib/zitadel"; +import { userService } from "#/lib/zitadel"; import { NextRequest, NextResponse } from "next/server"; export async function POST(request: NextRequest) { @@ -7,7 +7,8 @@ export async function POST(request: NextRequest) { const { userId, code } = body; // replace with resend Mail method once its implemented - return setEmail(server, userId) + return userService + .setEmail({ userId }) .then((resp) => { return NextResponse.json(resp); }) diff --git a/apps/login/app/api/session/route.ts b/apps/login/app/api/session/route.ts index 63f1f08e2..f827f7f74 100644 --- a/apps/login/app/api/session/route.ts +++ b/apps/login/app/api/session/route.ts @@ -1,4 +1,4 @@ -import { server, deleteSession } from "#/lib/zitadel"; +import { sessionService } from "#/lib/zitadel"; import { SessionCookie, getMostRecentSessionCookie, @@ -11,7 +11,7 @@ import { createSessionForIdpAndUpdateCookie, setSessionAndUpdateCookie, } from "#/utils/session"; -import { RequestChallenges } from "@zitadel/server"; +import { RequestChallenges } from "@zitadel/server/v2beta"; import { NextRequest, NextResponse } from "next/server"; export async function POST(request: NextRequest) { @@ -128,7 +128,8 @@ export async function DELETE(request: NextRequest) { if (id) { const session = await getSessionCookieById(id); - return deleteSession(server, session.id, session.token) + return sessionService + .deleteSession({ sessionId: session.id, sessionToken: session.token }) .then(() => { return removeSessionFromCookie(session) .then(() => { diff --git a/apps/login/app/api/verifyemail/route.ts b/apps/login/app/api/verifyemail/route.ts index 1b2ddd29d..d3932610d 100644 --- a/apps/login/app/api/verifyemail/route.ts +++ b/apps/login/app/api/verifyemail/route.ts @@ -1,4 +1,4 @@ -import { server, verifyEmail } from "#/lib/zitadel"; +import { userService } from "#/lib/zitadel"; import { NextRequest, NextResponse } from "next/server"; export async function POST(request: NextRequest) { @@ -6,7 +6,11 @@ export async function POST(request: NextRequest) { if (body) { const { userId, code } = body; - return verifyEmail(server, userId, code) + return userService + .verifyEmail({ + userId, + verificationCode: code, + }) .then((resp) => { return NextResponse.json(resp); }) diff --git a/apps/login/app/layout.tsx b/apps/login/app/layout.tsx index 2c4768fce..e984ca43f 100644 --- a/apps/login/app/layout.tsx +++ b/apps/login/app/layout.tsx @@ -2,12 +2,7 @@ import "#/styles/globals.scss"; import { AddressBar } from "#/ui/AddressBar"; import { GlobalNav } from "#/ui/GlobalNav"; import { Lato } from "next/font/google"; -import { LayoutProviders } from "#/ui/LayoutProviders"; import { Analytics } from "@vercel/analytics/react"; -import ThemeWrapper from "#/ui/ThemeWrapper"; -import { getBrandingSettings } from "#/lib/zitadel"; -import { server } from "../lib/zitadel"; -import { BrandingSettings } from "@zitadel/server"; import ThemeProvider from "#/ui/ThemeProvider"; import Theme from "#/ui/Theme"; diff --git a/apps/login/app/login/route.ts b/apps/login/app/login/route.ts index 10516eec3..434286b3e 100644 --- a/apps/login/app/login/route.ts +++ b/apps/login/app/login/route.ts @@ -1,17 +1,10 @@ -import { - createCallback, - getAuthRequest, - getOrgByDomain, - listSessions, - server, -} from "#/lib/zitadel"; +import { listSessions, managementService, oidcService } from "#/lib/zitadel"; import { SessionCookie, getAllSessions } from "#/utils/cookies"; -import { Session, AuthRequest, Prompt } from "@zitadel/server"; +import { Session, AuthRequest, Prompt } from "@zitadel/server/v2beta"; import { NextRequest, NextResponse } from "next/server"; async function loadSessions(ids: string[]): Promise { const response = await listSessions( - server, ids.filter((id: string | undefined) => !!id) ); @@ -74,7 +67,7 @@ export async function GET(request: NextRequest) { sessionToken: cookie?.token, }; - const { callbackUrl } = await createCallback(server, { + const { callbackUrl } = await oidcService.createCallback({ authRequestId, session, }); @@ -85,7 +78,7 @@ export async function GET(request: NextRequest) { if (authRequestId) { console.log(`Login with authRequest: ${authRequestId}`); - const { authRequest } = await getAuthRequest(server, { authRequestId }); + const { authRequest } = await oidcService.getAuthRequest({ authRequestId }); let organization; if (authRequest?.scope) { @@ -105,7 +98,9 @@ export async function GET(request: NextRequest) { const matched = ORG_DOMAIN_SCOPE_REGEX.exec(orgDomainScope); const orgDomain = matched?.[1] ?? ""; if (orgDomain) { - const org = await getOrgByDomain(orgDomain); + const org = await managementService.getOrgByDomain({ + domain: orgDomain, + }); organization = org?.org?.id ?? ""; } } @@ -165,7 +160,7 @@ export async function GET(request: NextRequest) { sessionId: cookie?.id, sessionToken: cookie?.token, }; - const { callbackUrl } = await createCallback(server, { + const { callbackUrl } = await oidcService.createCallback({ authRequestId, session, }); @@ -196,7 +191,7 @@ export async function GET(request: NextRequest) { sessionId: cookie?.id, sessionToken: cookie?.token, }; - const { callbackUrl } = await createCallback(server, { + const { callbackUrl } = await oidcService.createCallback({ authRequestId, session, }); diff --git a/apps/login/lib/zitadel.ts b/apps/login/lib/zitadel.ts index edaf9cc36..eb8415c0f 100644 --- a/apps/login/lib/zitadel.ts +++ b/apps/login/lib/zitadel.ts @@ -1,13 +1,5 @@ import { ZitadelServer, - ZitadelServerOptions, - user, - oidc, - settings, - getServers, - initializeServer, - session, - GetGeneralSettingsResponse, CreateSessionResponse, GetBrandingSettingsResponse, GetPasswordComplexitySettingsResponse, @@ -18,48 +10,38 @@ import { LegalAndSupportSettings, PasswordComplexitySettings, GetSessionResponse, - VerifyEmailResponse, SetSessionResponse, SetSessionRequest, ListUsersResponse, - management, - DeleteSessionResponse, - VerifyPasskeyRegistrationResponse, LoginSettings, - GetOrgByDomainGlobalResponse, GetLoginSettingsResponse, - ListAuthenticationMethodTypesResponse, - StartIdentityProviderIntentRequest, - StartIdentityProviderIntentResponse, - RetrieveIdentityProviderIntentRequest, - RetrieveIdentityProviderIntentResponse, - GetAuthRequestResponse, - GetAuthRequestRequest, - CreateCallbackRequest, - CreateCallbackResponse, RequestChallenges, - TextQueryMethod, AddHumanUserRequest, } from "@zitadel/server"; -export const zitadelConfig: ZitadelServerOptions = { - name: "zitadel login", - apiUrl: process.env.ZITADEL_API_URL ?? "", - token: process.env.ZITADEL_SERVICE_USER_TOKEN ?? "", -}; +import { + createSessionServiceClient, + createUserServiceClient, + createOIDCServiceClient, + createSettingsServiceClient, + TextQueryMethod, +} from "@zitadel/server/v2beta"; +import { createManagementServiceClient } from "@zitadel/server/v1"; -let server: ZitadelServer; +const server = new ZitadelServer({ + apiUrl: process.env.ZITADEL_API_URL, + token: process.env.ZITADEL_SERVICE_USER_TOKEN, +}); -if (!getServers().length) { - console.log("initialize server"); - server = initializeServer(zitadelConfig); -} +export const sessionService = createSessionServiceClient(server); +export const managementService = createManagementServiceClient(server); +export const userService = createUserServiceClient(server); +export const oidcService = createOIDCServiceClient(server); +export const settingsService = createSettingsServiceClient(server); export async function getBrandingSettings( - server: ZitadelServer, organization?: string ): Promise { - const settingsService = settings.getSettings(server); return settingsService .getBrandingSettings( { ctx: organization ? { orgId: organization } : { instance: true } }, @@ -69,29 +51,16 @@ export async function getBrandingSettings( } export async function getLoginSettings( - server: ZitadelServer, orgId?: string ): Promise { - const settingsService = settings.getSettings(server); return settingsService .getLoginSettings({ ctx: orgId ? { orgId } : { instance: true } }, {}) .then((resp: GetLoginSettingsResponse) => resp.settings); } -export async function getGeneralSettings( - server: ZitadelServer -): Promise { - const settingsService = settings.getSettings(server); - return settingsService - .getGeneralSettings({}, {}) - .then((resp: GetGeneralSettingsResponse) => resp.supportedLanguages); -} - export async function getLegalAndSupportSettings( - server: ZitadelServer, organization?: string ): Promise { - const settingsService = settings.getSettings(server); return settingsService .getLegalAndSupportSettings( { ctx: organization ? { orgId: organization } : { instance: true } }, @@ -103,11 +72,8 @@ export async function getLegalAndSupportSettings( } export async function getPasswordComplexitySettings( - server: ZitadelServer, organization?: string ): Promise { - const settingsService = settings.getSettings(server); - return settingsService .getPasswordComplexitySettings( organization @@ -119,12 +85,10 @@ export async function getPasswordComplexitySettings( } export async function createSessionForLoginname( - server: ZitadelServer, loginName: string, password: string | undefined, challenges: RequestChallenges | undefined ): Promise { - const sessionService = session.getSession(server); return password ? sessionService.createSession( { @@ -151,12 +115,10 @@ export async function createSessionForLoginname( } export async function createSessionForUserId( - server: ZitadelServer, userId: string, password: string | undefined, challenges: RequestChallenges | undefined ): Promise { - const sessionService = session.getSession(server); return password ? sessionService.createSession( { @@ -183,15 +145,12 @@ export async function createSessionForUserId( } export async function createSessionForUserIdAndIdpIntent( - server: ZitadelServer, userId: string, idpIntent: { idpIntentId?: string | undefined; idpIntentToken?: string | undefined; } ): Promise { - const sessionService = session.getSession(server); - return sessionService.createSession( { checks: { user: { userId }, idpIntent }, @@ -205,15 +164,12 @@ export async function createSessionForUserIdAndIdpIntent( } export async function setSession( - server: ZitadelServer, sessionId: string, sessionToken: string, password: string | undefined, webAuthN: { credentialAssertionData: any } | undefined, challenges: RequestChallenges | undefined ): Promise { - const sessionService = session.getSession(server); - const payload: SetSessionRequest = { sessionId, sessionToken, @@ -234,29 +190,15 @@ export async function setSession( } export async function getSession( - server: ZitadelServer, sessionId: string, sessionToken: string ): Promise { - const sessionService = session.getSession(server); return sessionService.getSession({ sessionId, sessionToken }, {}); } -export async function deleteSession( - server: ZitadelServer, - sessionId: string, - sessionToken: string -): Promise { - const sessionService = session.getSession(server); - return sessionService.deleteSession({ sessionId, sessionToken }, {}); -} - export async function listSessions( - server: ZitadelServer, ids: string[] ): Promise { - const sessionService = session.getSession(server); - const query = { offset: 0, limit: 100, asc: true }; const queries = [{ idsQuery: { ids } }]; return sessionService.listSessions({ queries: queries }, {}); } @@ -269,12 +211,13 @@ export type AddHumanUserData = { organization: string | undefined; }; -export async function addHumanUser( - server: ZitadelServer, - { email, firstName, lastName, password, organization }: AddHumanUserData -): Promise { - const userService = user.getUser(server); - +export async function addHumanUser({ + email, + firstName, + lastName, + password, + organization, +}: AddHumanUserData): Promise { const payload: Partial = { email: { email }, username: email, @@ -300,8 +243,6 @@ export async function listUsers( userName: string, organizationId: string ): Promise { - const userService = user.getUser(server); - return userService.listUsers( { queries: organizationId @@ -330,171 +271,3 @@ export async function listUsers( {} ); } - -export async function getOrgByDomain( - domain: string -): Promise { - const mgmtService = management.getManagement(server); - return mgmtService.getOrgByDomainGlobal({ domain }, {}); -} - -export async function startIdentityProviderFlow( - server: ZitadelServer, - { idpId, urls }: StartIdentityProviderIntentRequest -): Promise { - const userService = user.getUser(server); - - return userService.startIdentityProviderIntent({ - idpId, - urls, - }); -} - -export async function retrieveIdentityProviderInformation( - server: ZitadelServer, - { idpIntentId, idpIntentToken }: RetrieveIdentityProviderIntentRequest -): Promise { - const userService = user.getUser(server); - - return userService.retrieveIdentityProviderIntent({ - idpIntentId, - idpIntentToken, - }); -} - -export async function getAuthRequest( - server: ZitadelServer, - { authRequestId }: GetAuthRequestRequest -): Promise { - const oidcService = oidc.getOidc(server); - - return oidcService.getAuthRequest({ - authRequestId, - }); -} - -export async function createCallback( - server: ZitadelServer, - req: CreateCallbackRequest -): Promise { - const oidcService = oidc.getOidc(server); - - return oidcService.createCallback(req); -} - -export async function verifyEmail( - server: ZitadelServer, - userId: string, - verificationCode: string -): Promise { - const userservice = user.getUser(server); - return userservice.verifyEmail( - { - userId, - verificationCode, - }, - {} - ); -} - -/** - * - * @param server - * @param userId the id of the user where the email should be set - * @returns the newly set email - */ -export async function setEmail( - server: ZitadelServer, - userId: string -): Promise { - const userservice = user.getUser(server); - return userservice.setEmail( - { - userId, - }, - {} - ); -} - -/** - * - * @param server - * @param userId the id of the user where the email should be set - * @returns the newly set email - */ -export async function createPasskeyRegistrationLink( - userId: string -): Promise { - const userservice = user.getUser(server); - - return userservice.createPasskeyRegistrationLink({ - userId, - returnCode: {}, - }); -} - -/** - * - * @param server - * @param userId the id of the user where the email should be set - * @returns the newly set email - */ -export async function verifyPasskeyRegistration( - server: ZitadelServer, - passkeyId: string, - passkeyName: string, - publicKeyCredential: - | { - [key: string]: any; - } - | undefined, - userId: string -): Promise { - const userservice = user.getUser(server); - return userservice.verifyPasskeyRegistration( - { - passkeyId, - passkeyName, - publicKeyCredential, - userId, - }, - {} - ); -} - -/** - * - * @param server - * @param userId the id of the user where the email should be set - * @returns the newly set email - */ -export async function registerPasskey( - userId: string, - code: { id: string; code: string }, - domain: string -): Promise { - const userservice = user.getUser(server); - return userservice.registerPasskey({ - userId, - code, - domain, - // authenticator: - }); -} - -/** - * - * @param server - * @param userId the id of the user where the email should be set - * @returns the newly set email - */ -export async function listAuthenticationMethodTypes( - userId: string -): Promise { - const userservice = user.getUser(server); - return userservice.listAuthenticationMethodTypes({ - userId, - }); -} - -export { server }; diff --git a/apps/login/ui/DynamicTheme.tsx b/apps/login/ui/DynamicTheme.tsx index 468e323ea..02f607184 100644 --- a/apps/login/ui/DynamicTheme.tsx +++ b/apps/login/ui/DynamicTheme.tsx @@ -1,6 +1,6 @@ "use client"; -import { BrandingSettings } from "@zitadel/server"; +import { BrandingSettings } from "@zitadel/server/v2beta"; import React from "react"; import { Logo } from "#/ui/Logo"; import ThemeWrapper from "./ThemeWrapper"; diff --git a/apps/login/ui/PasswordComplexity.tsx b/apps/login/ui/PasswordComplexity.tsx index 732957238..2dc65f4f0 100644 --- a/apps/login/ui/PasswordComplexity.tsx +++ b/apps/login/ui/PasswordComplexity.tsx @@ -4,7 +4,7 @@ import { symbolValidator, upperCaseValidator, } from "#/utils/validators"; -import { PasswordComplexitySettings } from "@zitadel/server"; +import { PasswordComplexitySettings } from "@zitadel/server/v2beta"; type Props = { passwordComplexitySettings: PasswordComplexitySettings; diff --git a/apps/login/ui/PrivacyPolicyCheckboxes.tsx b/apps/login/ui/PrivacyPolicyCheckboxes.tsx index da94e428c..7ab7600ef 100644 --- a/apps/login/ui/PrivacyPolicyCheckboxes.tsx +++ b/apps/login/ui/PrivacyPolicyCheckboxes.tsx @@ -2,7 +2,7 @@ import React, { useState } from "react"; import Link from "next/link"; import { Checkbox } from "./Checkbox"; -import { LegalAndSupportSettings } from "@zitadel/server"; +import { LegalAndSupportSettings } from "@zitadel/server/v2beta"; type Props = { legal: LegalAndSupportSettings; diff --git a/apps/login/ui/RegisterFormWithoutPassword.tsx b/apps/login/ui/RegisterFormWithoutPassword.tsx index 977ed5fd0..2f39be607 100644 --- a/apps/login/ui/RegisterFormWithoutPassword.tsx +++ b/apps/login/ui/RegisterFormWithoutPassword.tsx @@ -1,6 +1,6 @@ "use client"; -import { LegalAndSupportSettings } from "@zitadel/server"; +import { LegalAndSupportSettings } from "@zitadel/server/v2beta"; import { useState } from "react"; import { Button, ButtonVariants } from "./Button"; import { TextInput } from "./Input"; diff --git a/apps/login/ui/RegisterPasskey.tsx b/apps/login/ui/RegisterPasskey.tsx index 41febc7a8..770a00537 100644 --- a/apps/login/ui/RegisterPasskey.tsx +++ b/apps/login/ui/RegisterPasskey.tsx @@ -6,7 +6,7 @@ import { useForm } from "react-hook-form"; import { useRouter } from "next/navigation"; import { Spinner } from "./Spinner"; import Alert from "./Alert"; -import { AuthRequest, RegisterPasskeyResponse } from "@zitadel/server"; +import { AuthRequest, RegisterPasskeyResponse } from "@zitadel/server/v2beta"; import { coerceToArrayBuffer, coerceToBase64Url } from "#/utils/base64"; type Inputs = {}; diff --git a/apps/login/ui/SessionItem.tsx b/apps/login/ui/SessionItem.tsx index f37be1196..5da4e9ecd 100644 --- a/apps/login/ui/SessionItem.tsx +++ b/apps/login/ui/SessionItem.tsx @@ -1,5 +1,5 @@ "use client"; -import { Session } from "@zitadel/server"; +import { Session } from "@zitadel/server/v2beta"; import Link from "next/link"; import { useState } from "react"; import { Avatar } from "./Avatar"; diff --git a/apps/login/ui/SessionsList.tsx b/apps/login/ui/SessionsList.tsx index a7e0c4cfa..8f0240f4a 100644 --- a/apps/login/ui/SessionsList.tsx +++ b/apps/login/ui/SessionsList.tsx @@ -1,6 +1,6 @@ "use client"; -import { Session } from "@zitadel/server"; +import { Session } from "@zitadel/server/v2beta"; import SessionItem from "./SessionItem"; import Alert from "./Alert"; import { useEffect, useState } from "react"; diff --git a/apps/login/ui/SetPasswordForm.tsx b/apps/login/ui/SetPasswordForm.tsx index 5460b70bc..06894873c 100644 --- a/apps/login/ui/SetPasswordForm.tsx +++ b/apps/login/ui/SetPasswordForm.tsx @@ -1,6 +1,6 @@ "use client"; -import { PasswordComplexitySettings } from "@zitadel/server"; +import { PasswordComplexitySettings } from "@zitadel/server/v2beta"; import PasswordComplexity from "./PasswordComplexity"; import { useState } from "react"; import { Button, ButtonVariants } from "./Button"; diff --git a/apps/login/ui/ThemeWrapper.tsx b/apps/login/ui/ThemeWrapper.tsx index b8caf797d..23bc87b51 100644 --- a/apps/login/ui/ThemeWrapper.tsx +++ b/apps/login/ui/ThemeWrapper.tsx @@ -1,6 +1,6 @@ "use client"; -import { BrandingSettings } from "@zitadel/server"; +import { BrandingSettings } from "@zitadel/server/v2beta"; import { setTheme } from "#/utils/colors"; import { useEffect } from "react"; diff --git a/apps/login/ui/UsernameForm.tsx b/apps/login/ui/UsernameForm.tsx index 9f4719b7e..9ba2e917c 100644 --- a/apps/login/ui/UsernameForm.tsx +++ b/apps/login/ui/UsernameForm.tsx @@ -6,7 +6,7 @@ import { TextInput } from "./Input"; import { useForm } from "react-hook-form"; import { useRouter } from "next/navigation"; import { Spinner } from "./Spinner"; -import { LoginSettings } from "@zitadel/server"; +import { LoginSettings } from "@zitadel/server/v2beta"; import Alert from "./Alert"; type Inputs = { diff --git a/apps/login/utils/colors.ts b/apps/login/utils/colors.ts index 817f3eb36..bd9a92e1a 100644 --- a/apps/login/utils/colors.ts +++ b/apps/login/utils/colors.ts @@ -1,6 +1,6 @@ import tinycolor from "tinycolor2"; -import { BrandingSettings } from "@zitadel/server"; +import { BrandingSettings } from "@zitadel/server/v2beta"; export interface Color { name: string; diff --git a/apps/login/utils/session.ts b/apps/login/utils/session.ts index 55f0a14dc..ea269a06e 100644 --- a/apps/login/utils/session.ts +++ b/apps/login/utils/session.ts @@ -5,7 +5,6 @@ import { createSessionForUserId, createSessionForUserIdAndIdpIntent, getSession, - server, setSession, } from "#/lib/zitadel"; import { @@ -13,7 +12,7 @@ import { addSessionToCookie, updateSessionCookie, } from "./cookies"; -import { Session, Challenges, RequestChallenges } from "@zitadel/server"; +import { Session, Challenges, RequestChallenges } from "@zitadel/server/v2beta"; export async function createSessionAndUpdateCookie( loginName: string, @@ -23,7 +22,6 @@ export async function createSessionAndUpdateCookie( authRequestId?: string ): Promise { const createdSession = await createSessionForLoginname( - server, loginName, password, challenges @@ -31,7 +29,6 @@ export async function createSessionAndUpdateCookie( if (createdSession) { return getSession( - server, createdSession.sessionId, createdSession.sessionToken ).then((response) => { @@ -73,7 +70,6 @@ export async function createSessionForUserIdAndUpdateCookie( authRequestId: string | undefined ): Promise { const createdSession = await createSessionForUserId( - server, userId, password, challenges @@ -81,7 +77,6 @@ export async function createSessionForUserIdAndUpdateCookie( if (createdSession) { return getSession( - server, createdSession.sessionId, createdSession.sessionToken ).then((response) => { @@ -126,14 +121,12 @@ export async function createSessionForIdpAndUpdateCookie( authRequestId: string | undefined ): Promise { const createdSession = await createSessionForUserIdAndIdpIntent( - server, userId, idpIntent ); if (createdSession) { return getSession( - server, createdSession.sessionId, createdSession.sessionToken ).then((response) => { @@ -180,7 +173,6 @@ export async function setSessionAndUpdateCookie( authRequestId: string | undefined ): Promise { return setSession( - server, recentCookie.id, recentCookie.token, password, @@ -204,37 +196,30 @@ export async function setSessionAndUpdateCookie( return new Promise((resolve) => setTimeout(resolve, 1000)).then(() => // TODO: remove - getSession(server, sessionCookie.id, sessionCookie.token).then( - (response) => { - if ( - response?.session && - response.session.factors?.user?.loginName - ) { - const { session } = response; - const newCookie: SessionCookie = { - id: sessionCookie.id, - token: updatedSession.sessionToken, - creationDate: sessionCookie.creationDate, - expirationDate: sessionCookie.expirationDate, - changeDate: `${session.changeDate?.getTime() ?? ""}`, - loginName: session.factors?.user?.loginName ?? "", - organization: session.factors?.user?.organizationId ?? "", - }; - - if (sessionCookie.authRequestId) { - newCookie.authRequestId = sessionCookie.authRequestId; - } - - return updateSessionCookie(sessionCookie.id, newCookie).then( - () => { - return { challenges: updatedSession.challenges, ...session }; - } - ); - } else { - throw "could not get session or session does not have loginName"; + getSession(sessionCookie.id, sessionCookie.token).then((response) => { + if (response?.session && response.session.factors?.user?.loginName) { + const { session } = response; + const newCookie: SessionCookie = { + id: sessionCookie.id, + token: updatedSession.sessionToken, + creationDate: sessionCookie.creationDate, + expirationDate: sessionCookie.expirationDate, + changeDate: `${session.changeDate?.getTime() ?? ""}`, + loginName: session.factors?.user?.loginName ?? "", + organization: session.factors?.user?.organizationId ?? "", + }; + + if (sessionCookie.authRequestId) { + newCookie.authRequestId = sessionCookie.authRequestId; } + + return updateSessionCookie(sessionCookie.id, newCookie).then(() => { + return { challenges: updatedSession.challenges, ...session }; + }); + } else { + throw "could not get session or session does not have loginName"; } - ) + }) ); } else { throw "Session not be set"; diff --git a/packages/zitadel-client/jest.config.ts b/packages/zitadel-client/jest.config.ts index fadf29ddd..e6ac62e86 100644 --- a/packages/zitadel-client/jest.config.ts +++ b/packages/zitadel-client/jest.config.ts @@ -1,8 +1,8 @@ -import type { JestConfigWithTsJest } from 'ts-jest' +import type { JestConfigWithTsJest } from "ts-jest"; const jestConfig: JestConfigWithTsJest = { - preset: 'ts-jest', - testEnvironment: 'node' -} + preset: "ts-jest", + testEnvironment: "node", +}; -export default jestConfig \ No newline at end of file +export default jestConfig; diff --git a/packages/zitadel-client/src/middleware.test.ts b/packages/zitadel-client/src/middleware.test.ts index 5b4ae7059..4d075afe9 100644 --- a/packages/zitadel-client/src/middleware.test.ts +++ b/packages/zitadel-client/src/middleware.test.ts @@ -1,57 +1,74 @@ -import { CallOptions, ClientMiddlewareCall, Metadata, MethodDescriptor } from "nice-grpc-web"; +import { + CallOptions, + ClientMiddlewareCall, + Metadata, + MethodDescriptor, +} from "nice-grpc-web"; import { authMiddleware } from "./middleware"; -describe('authMiddleware', () => { - const scenarios = [ - { - name: 'should add authorization if metadata is undefined', - initialMetadata: undefined, - expectedMetadata: new Metadata().set("authorization", "Bearer mock-token"), - token: "mock-token" - }, - { - name: 'should add authorization if metadata exists but no authorization', - initialMetadata: new Metadata().set("other-key", "other-value"), - expectedMetadata: new Metadata().set("other-key", "other-value").set("authorization", "Bearer mock-token"), - token: "mock-token" - }, - { - name: 'should not modify authorization if it already exists', - initialMetadata: new Metadata().set("authorization", "Bearer initial-token"), - expectedMetadata: new Metadata().set("authorization", "Bearer initial-token"), - token: "mock-token" - }, - ]; +describe("authMiddleware", () => { + const scenarios = [ + { + name: "should add authorization if metadata is undefined", + initialMetadata: undefined, + expectedMetadata: new Metadata().set( + "authorization", + "Bearer mock-token" + ), + token: "mock-token", + }, + { + name: "should add authorization if metadata exists but no authorization", + initialMetadata: new Metadata().set("other-key", "other-value"), + expectedMetadata: new Metadata() + .set("other-key", "other-value") + .set("authorization", "Bearer mock-token"), + token: "mock-token", + }, + { + name: "should not modify authorization if it already exists", + initialMetadata: new Metadata().set( + "authorization", + "Bearer initial-token" + ), + expectedMetadata: new Metadata().set( + "authorization", + "Bearer initial-token" + ), + token: "mock-token", + }, + ]; - scenarios.forEach(({ name, initialMetadata, expectedMetadata, token }) => { - it(name, async () => { + scenarios.forEach(({ name, initialMetadata, expectedMetadata, token }) => { + it(name, async () => { + const mockNext = jest.fn().mockImplementation(async function* () {}); + const mockRequest = {}; - const mockNext = jest.fn().mockImplementation(async function*() { }); - const mockRequest = {}; + const mockMethodDescriptor: MethodDescriptor = { + options: { idempotencyLevel: undefined }, + path: "", + requestStream: false, + responseStream: false, + }; - const mockMethodDescriptor: MethodDescriptor = { - options: {idempotencyLevel: undefined}, - path: '', - requestStream: false, - responseStream: false, - }; + const mockCall: ClientMiddlewareCall = { + method: mockMethodDescriptor, + requestStream: false, + responseStream: false, + request: mockRequest, + next: mockNext, + }; + const options: CallOptions = { + metadata: initialMetadata, + }; - const mockCall: ClientMiddlewareCall = { - method: mockMethodDescriptor, - requestStream: false, - responseStream: false, - request: mockRequest, - next: mockNext, - }; - const options: CallOptions = { - metadata: initialMetadata - }; + await authMiddleware(token)(mockCall, options).next(); - await authMiddleware(token)(mockCall, options).next(); - - expect(mockNext).toHaveBeenCalledTimes(1); - const actualMetadata = mockNext.mock.calls[0][1].metadata; - expect(actualMetadata?.get('authorization')).toEqual(expectedMetadata.get('authorization')); - }); + expect(mockNext).toHaveBeenCalledTimes(1); + const actualMetadata = mockNext.mock.calls[0][1].metadata; + expect(actualMetadata?.get("authorization")).toEqual( + expectedMetadata.get("authorization") + ); }); }); +}); diff --git a/packages/zitadel-next/jest.config.ts b/packages/zitadel-next/jest.config.ts index fadf29ddd..e6ac62e86 100644 --- a/packages/zitadel-next/jest.config.ts +++ b/packages/zitadel-next/jest.config.ts @@ -1,8 +1,8 @@ -import type { JestConfigWithTsJest } from 'ts-jest' +import type { JestConfigWithTsJest } from "ts-jest"; const jestConfig: JestConfigWithTsJest = { - preset: 'ts-jest', - testEnvironment: 'node' -} + preset: "ts-jest", + testEnvironment: "node", +}; -export default jestConfig \ No newline at end of file +export default jestConfig; diff --git a/packages/zitadel-react/jest.config.ts b/packages/zitadel-react/jest.config.ts index d79ec0f6f..a9be60345 100644 --- a/packages/zitadel-react/jest.config.ts +++ b/packages/zitadel-react/jest.config.ts @@ -1,9 +1,9 @@ -import type { JestConfigWithTsJest } from 'ts-jest' +import type { JestConfigWithTsJest } from "ts-jest"; const jestConfig: JestConfigWithTsJest = { - preset: 'ts-jest', - testEnvironment: 'jsdom', - setupFilesAfterEnv: [ '@testing-library/jest-dom/extend-expect' ] -} + preset: "ts-jest", + testEnvironment: "jsdom", + setupFilesAfterEnv: ["@testing-library/jest-dom/extend-expect"], +}; -export default jestConfig \ No newline at end of file +export default jestConfig; diff --git a/packages/zitadel-server/buf.gen.yaml b/packages/zitadel-server/buf.gen.yaml index 0dbd909c2..29bf68105 100644 --- a/packages/zitadel-server/buf.gen.yaml +++ b/packages/zitadel-server/buf.gen.yaml @@ -15,4 +15,4 @@ plugins: - useExactTypes=false # - plugin: buf.build/protocolbuffers/js # out: src/app/proto/generated - # opt: import_style=commonjs,binary \ No newline at end of file + # opt: import_style=commonjs,binary diff --git a/packages/zitadel-server/jest.config.ts b/packages/zitadel-server/jest.config.ts index fadf29ddd..e6ac62e86 100644 --- a/packages/zitadel-server/jest.config.ts +++ b/packages/zitadel-server/jest.config.ts @@ -1,8 +1,8 @@ -import type { JestConfigWithTsJest } from 'ts-jest' +import type { JestConfigWithTsJest } from "ts-jest"; const jestConfig: JestConfigWithTsJest = { - preset: 'ts-jest', - testEnvironment: 'node' -} + preset: "ts-jest", + testEnvironment: "node", +}; -export default jestConfig \ No newline at end of file +export default jestConfig; diff --git a/packages/zitadel-server/package.json b/packages/zitadel-server/package.json index df1ac582b..e2635bea5 100644 --- a/packages/zitadel-server/package.json +++ b/packages/zitadel-server/package.json @@ -1,12 +1,31 @@ { "name": "@zitadel/server", "version": "0.0.0", - "main": "./dist/index.js", - "module": "./dist/index.mjs", - "types": "./dist/index.d.ts", "type": "commonjs", "sideEffects": false, "license": "MIT", + "exports": { + ".": { + "import": "./dist/index.mjs", + "require": "./dist/index.js", + "types": "./dist/index.d.ts" + }, + "./v1": { + "import": "./dist/v1.mjs", + "require": "./dist/v1.js", + "types": "./dist/v1.d.ts" + }, + "./v2beta": { + "import": "./dist/v2beta.mjs", + "require": "./dist/v2beta.js", + "types": "./dist/v2beta.d.ts" + }, + "./v3alpha": { + "import": "./dist/v3alpha.mjs", + "require": "./dist/v3alpha.js", + "types": "./dist/v3alpha.d.ts" + } + }, "files": [ "dist/**" ], @@ -44,4 +63,4 @@ "nice-grpc-common": "^2.0.2", "protobufjs": "^7.2.3" } -} \ No newline at end of file +} diff --git a/packages/zitadel-server/src/admin/admin.ts b/packages/zitadel-server/src/admin/admin.ts deleted file mode 100644 index b8eae571e..000000000 --- a/packages/zitadel-server/src/admin/admin.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; - -import { createChannel, createClientFactory } from "nice-grpc"; -import { - AdminServiceClient, - AdminServiceDefinition, -} from "../proto/server/zitadel/admin"; -import { authMiddleware } from "../middleware"; - -const createClient = ( - definition: CompatServiceDefinition, - accessToken: string -) => { - const channel = createChannel(process.env.ZITADEL_API_URL ?? ""); - return createClientFactory() - .use(authMiddleware(accessToken)) - .create(definition, channel) as Client; -}; - -export const getAdmin = () => - createClient( - AdminServiceDefinition as CompatServiceDefinition, - process.env.ZITADEL_ADMIN_TOKEN ?? "" - ); diff --git a/packages/zitadel-server/src/admin/index.ts b/packages/zitadel-server/src/admin/index.ts deleted file mode 100644 index 2dc46f523..000000000 --- a/packages/zitadel-server/src/admin/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./admin"; diff --git a/packages/zitadel-server/src/auth/auth.ts b/packages/zitadel-server/src/auth/auth.ts deleted file mode 100644 index f39e96a55..000000000 --- a/packages/zitadel-server/src/auth/auth.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; -import { createChannel, createClientFactory } from "nice-grpc"; -import { - AuthServiceClient, - AuthServiceDefinition, - GetMyUserResponse, -} from "../proto/server/zitadel/auth"; -import { ZitadelServer } from "../server"; -import { authMiddleware } from "../middleware"; - -const createClient = ( - definition: CompatServiceDefinition, - accessToken: string -) => { - const channel = createChannel(process.env.ZITADEL_API_URL ?? ""); - return createClientFactory() - .use(authMiddleware(accessToken)) - .create(definition, channel) as Client; -}; - -export async function getAuth(app?: ZitadelServer): Promise { - return createClient( - AuthServiceDefinition as CompatServiceDefinition, - "" - ); -} - -export async function getMyUser(): Promise { - const auth = await getAuth(); - const response = await auth.getMyUser({}); - return response; -} diff --git a/packages/zitadel-server/src/auth/index.ts b/packages/zitadel-server/src/auth/index.ts deleted file mode 100644 index a5dfbee9d..000000000 --- a/packages/zitadel-server/src/auth/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "../proto/server/zitadel/auth"; -export { getAuth } from "./auth"; diff --git a/packages/zitadel-server/src/index.ts b/packages/zitadel-server/src/index.ts index 6ec282fe7..f3fc050dc 100644 --- a/packages/zitadel-server/src/index.ts +++ b/packages/zitadel-server/src/index.ts @@ -1,118 +1 @@ -import * as settings from "./v2/settings"; -import * as session from "./v2/session"; -import * as user from "./v2/user"; -import * as oidc from "./v2/oidc"; -import * as management from "./management"; - -import * as login from "./proto/server/zitadel/settings/v2beta/login_settings"; -import * as password from "./proto/server/zitadel/settings/v2beta/password_settings"; -import * as legal from "./proto/server/zitadel/settings/v2beta/legal_settings"; - -export { - BrandingSettings, - Theme, -} from "./proto/server/zitadel/settings/v2beta/branding_settings"; - -export { - LoginSettings, - IdentityProvider, - IdentityProviderType, -} from "./proto/server/zitadel/settings/v2beta/login_settings"; - -export { - RequestChallenges, - Challenges, - Challenges_WebAuthN, -} from "./proto/server/zitadel/session/v2beta/challenge"; - -export { - GetAuthRequestRequest, - GetAuthRequestResponse, - CreateCallbackRequest, - CreateCallbackResponse, -} from "./proto/server/zitadel/oidc/v2beta/oidc_service"; - -export { - AuthRequest, - Prompt, -} from "./proto/server/zitadel/oidc/v2beta/authorization"; - -export { - Session, - Factors, -} from "./proto/server/zitadel/session/v2beta/session"; -export { - IDPInformation, - IDPLink, -} from "./proto/server/zitadel/user/v2beta/idp"; -export { - ListSessionsResponse, - GetSessionResponse, - CreateSessionResponse, - SetSessionResponse, - SetSessionRequest, - DeleteSessionResponse, -} from "./proto/server/zitadel/session/v2beta/session_service"; -export { - GetPasswordComplexitySettingsResponse, - GetBrandingSettingsResponse, - GetLegalAndSupportSettingsResponse, - GetGeneralSettingsResponse, - GetLoginSettingsResponse, - GetLoginSettingsRequest, - GetActiveIdentityProvidersResponse, - GetActiveIdentityProvidersRequest, -} from "./proto/server/zitadel/settings/v2beta/settings_service"; -export { TextQueryMethod } from "./proto/server/zitadel/object/v2beta/object"; -export { - AddHumanUserResponse, - AddHumanUserRequest, - VerifyEmailResponse, - VerifyPasskeyRegistrationRequest, - VerifyPasskeyRegistrationResponse, - RegisterPasskeyRequest, - RegisterPasskeyResponse, - CreatePasskeyRegistrationLinkResponse, - CreatePasskeyRegistrationLinkRequest, - ListAuthenticationMethodTypesResponse, - ListAuthenticationMethodTypesRequest, - AuthenticationMethodType, - StartIdentityProviderIntentRequest, - StartIdentityProviderIntentResponse, - RetrieveIdentityProviderIntentRequest, - RetrieveIdentityProviderIntentResponse, - ListUsersRequest, - ListUsersResponse, -} from "./proto/server/zitadel/user/v2beta/user_service"; -export { - SetHumanPasswordResponse, - SetHumanPasswordRequest, - GetOrgByDomainGlobalResponse, -} from "./proto/server/zitadel/management"; -export * from "./proto/server/zitadel/idp"; -export { type LegalAndSupportSettings } from "./proto/server/zitadel/settings/v2beta/legal_settings"; -export { type PasswordComplexitySettings } from "./proto/server/zitadel/settings/v2beta/password_settings"; -export { type ResourceOwnerType } from "./proto/server/zitadel/settings/v2beta/settings"; - -import { - getServers, - initializeServer, - ZitadelServer, - ZitadelServerOptions, -} from "./server"; -export * from "./middleware"; - -export { - getServers, - ZitadelServer, - type ZitadelServerOptions, - initializeServer, - user, - management, - session, - settings, - login, - password, - legal, - oidc, -}; +export { ZitadelServer } from "./server"; diff --git a/packages/zitadel-server/src/internal.ts b/packages/zitadel-server/src/internal.ts deleted file mode 100644 index 34ba3eecb..000000000 --- a/packages/zitadel-server/src/internal.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { ZitadelServer } from "./server"; - -export const _servers = new Map(); diff --git a/packages/zitadel-server/src/management/index.ts b/packages/zitadel-server/src/management/index.ts deleted file mode 100644 index 5df1ddd31..000000000 --- a/packages/zitadel-server/src/management/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./management"; -export * as management from "../proto/server/zitadel/management"; -export * as policy from "../proto/server/zitadel/policy"; diff --git a/packages/zitadel-server/src/management/management.ts b/packages/zitadel-server/src/management/management.ts deleted file mode 100644 index 2a8c1e6b6..000000000 --- a/packages/zitadel-server/src/management/management.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; - -import { createChannel, createClientFactory } from "nice-grpc"; -import { - ManagementServiceClient, - ManagementServiceDefinition, -} from "../proto/server/zitadel/management"; - -import { authMiddleware } from "../middleware"; -import { ZitadelServer, getServers } from "../server"; - -const createClient = ( - definition: CompatServiceDefinition, - apiUrl: string, - token: string -) => { - if (!apiUrl) { - throw Error("ZITADEL_API_URL not set"); - } - - const channel = createChannel(process.env.ZITADEL_API_URL ?? ""); - return createClientFactory() - .use(authMiddleware(token)) - .create(definition, channel) as Client; -}; - -export const getManagement = (app?: string | ZitadelServer) => { - let config; - if (app && typeof app === "string") { - const apps = getServers(); - config = apps.find((a) => a.name === app)?.config; - } else if (app && typeof app === "object") { - config = app.config; - } - - if (!config) { - throw Error("No ZITADEL app found"); - } - - return createClient( - ManagementServiceDefinition as CompatServiceDefinition, - config.apiUrl, - config.token - ); -}; diff --git a/packages/zitadel-server/src/middleware.test.ts b/packages/zitadel-server/src/middleware.test.ts index 1d6768a8d..7ca61029c 100644 --- a/packages/zitadel-server/src/middleware.test.ts +++ b/packages/zitadel-server/src/middleware.test.ts @@ -1,57 +1,74 @@ -import { CallOptions, ClientMiddlewareCall, Metadata, MethodDescriptor } from "nice-grpc"; +import { + CallOptions, + ClientMiddlewareCall, + Metadata, + MethodDescriptor, +} from "nice-grpc"; import { authMiddleware } from "./middleware"; -describe('authMiddleware', () => { - const scenarios = [ - { - name: 'should add authorization if metadata is undefined', - initialMetadata: undefined, - expectedMetadata: new Metadata().set("authorization", "Bearer mock-token"), - token: "mock-token" - }, - { - name: 'should add authorization if metadata exists but no authorization', - initialMetadata: new Metadata().set("other-key", "other-value"), - expectedMetadata: new Metadata().set("other-key", "other-value").set("authorization", "Bearer mock-token"), - token: "mock-token" - }, - { - name: 'should not modify authorization if it already exists', - initialMetadata: new Metadata().set("authorization", "Bearer initial-token"), - expectedMetadata: new Metadata().set("authorization", "Bearer initial-token"), - token: "mock-token" - }, - ]; +describe("authMiddleware", () => { + const scenarios = [ + { + name: "should add authorization if metadata is undefined", + initialMetadata: undefined, + expectedMetadata: new Metadata().set( + "authorization", + "Bearer mock-token" + ), + token: "mock-token", + }, + { + name: "should add authorization if metadata exists but no authorization", + initialMetadata: new Metadata().set("other-key", "other-value"), + expectedMetadata: new Metadata() + .set("other-key", "other-value") + .set("authorization", "Bearer mock-token"), + token: "mock-token", + }, + { + name: "should not modify authorization if it already exists", + initialMetadata: new Metadata().set( + "authorization", + "Bearer initial-token" + ), + expectedMetadata: new Metadata().set( + "authorization", + "Bearer initial-token" + ), + token: "mock-token", + }, + ]; - scenarios.forEach(({ name, initialMetadata, expectedMetadata, token }) => { - it(name, async () => { + scenarios.forEach(({ name, initialMetadata, expectedMetadata, token }) => { + it(name, async () => { + const mockNext = jest.fn().mockImplementation(async function* () {}); + const mockRequest = {}; - const mockNext = jest.fn().mockImplementation(async function*() { }); - const mockRequest = {}; + const mockMethodDescriptor: MethodDescriptor = { + options: { idempotencyLevel: undefined }, + path: "", + requestStream: false, + responseStream: false, + }; - const mockMethodDescriptor: MethodDescriptor = { - options: {idempotencyLevel: undefined}, - path: '', - requestStream: false, - responseStream: false, - }; + const mockCall: ClientMiddlewareCall = { + method: mockMethodDescriptor, + requestStream: false, + responseStream: false, + request: mockRequest, + next: mockNext, + }; + const options: CallOptions = { + metadata: initialMetadata, + }; - const mockCall: ClientMiddlewareCall = { - method: mockMethodDescriptor, - requestStream: false, - responseStream: false, - request: mockRequest, - next: mockNext, - }; - const options: CallOptions = { - metadata: initialMetadata - }; + await authMiddleware(token)(mockCall, options).next(); - await authMiddleware(token)(mockCall, options).next(); - - expect(mockNext).toHaveBeenCalledTimes(1); - const actualMetadata = mockNext.mock.calls[0][1].metadata; - expect(actualMetadata?.get('authorization')).toEqual(expectedMetadata.get('authorization')); - }); + expect(mockNext).toHaveBeenCalledTimes(1); + const actualMetadata = mockNext.mock.calls[0][1].metadata; + expect(actualMetadata?.get("authorization")).toEqual( + expectedMetadata.get("authorization") + ); }); }); +}); diff --git a/packages/zitadel-server/src/middleware.ts b/packages/zitadel-server/src/middleware.ts index b9a86d92d..3cbbbd8a8 100644 --- a/packages/zitadel-server/src/middleware.ts +++ b/packages/zitadel-server/src/middleware.ts @@ -1,13 +1,19 @@ -import { CallOptions, ClientMiddleware, ClientMiddlewareCall, Metadata } from "nice-grpc"; +import { + CallOptions, + ClientMiddleware, + ClientMiddlewareCall, + Metadata, +} from "nice-grpc"; -export function authMiddleware (token: string): ClientMiddleware { +export function authMiddleware(token: string): ClientMiddleware { return async function* ( call: ClientMiddlewareCall, options: CallOptions ) { - if (!options.metadata?.has("authorization")) { - options.metadata ??= new Metadata(); - options.metadata?.set("authorization", `Bearer ${token}`); + options.metadata ??= new Metadata(); + + if (!options.metadata.has("authorization")) { + options.metadata.set("authorization", `Bearer ${token}`); } return yield* call.next(call.request, options); diff --git a/packages/zitadel-server/src/server.ts b/packages/zitadel-server/src/server.ts index 62ba9566e..66a0a245d 100644 --- a/packages/zitadel-server/src/server.ts +++ b/packages/zitadel-server/src/server.ts @@ -1,70 +1,46 @@ -import { createChannel, createClientFactory } from "nice-grpc"; -import { authMiddleware } from "./middleware"; +import { createChannel, createClientFactory, Channel } from "nice-grpc"; +import { importPKCS8, SignJWT } from "jose"; import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; -let apps: ZitadelServer[] = []; +import { authMiddleware } from "./middleware"; -export interface ZitadelServerProps { - apiUrl: string; // process.env.ZITADEL_API_URL +export type ZitadelServerConfig = { + apiUrl: string; token: string; -} - -export interface ZitadelServerOptions extends ZitadelServerProps { - name?: string; -} - -export function initializeServer( - config: ZitadelServerProps, - name?: string -): ZitadelServer { - const server = new ZitadelServer(config, name); - return server; -} +}; export class ZitadelServer { - name: string | undefined; - config: ZitadelServerProps; + token: string; + channel: Channel; - constructor(config: ZitadelServerProps, name?: string) { - if (name) { - this.name = name; + constructor(config: ZitadelServerConfig) { + if (!config.apiUrl) { + throw Error("config.apiUrl not set"); } - this.config = config; + + this.token = config.token; + this.channel = createChannel(config.apiUrl); } } -export function getServers(): ZitadelServer[] { - return apps; +export function createClientFor< + TClient, + Service extends CompatServiceDefinition = any +>(definition: Service) { + return (server: ZitadelServer): TClient => { + return createClientFactory() + .use(authMiddleware(server.token)) + .create(definition, server.channel) as TClient; + }; } -export function getServer(name?: string): ZitadelServer { - if (name) { - const found = apps.find((a) => a.name === name); - if (found) { - return found; - } else { - throw new Error("No server found"); - } - } else { - if (apps.length) { - return apps[0]; - } else { - throw new Error("No server found"); - } - } +export async function newSystemToken() { + return await new SignJWT({}) + .setProtectedHeader({ alg: "RS256" }) + .setIssuedAt() + .setExpirationTime("1h") + .setIssuer(process.env.ZITADEL_SYSTEM_API_USERID ?? "") + .setSubject(process.env.ZITADEL_SYSTEM_API_USERID ?? "") + .setAudience(process.env.ZITADEL_ISSUER ?? "") + .sign(await importPKCS8(process.env.ZITADEL_SYSTEM_API_KEY ?? "", "RS256")); } - -export const createClient = ( - definition: CompatServiceDefinition, - apiUrl: string, - token: string -) => { - if (!apiUrl) { - throw Error("ZITADEL_API_URL not set"); - } - - const channel = createChannel(process.env.ZITADEL_API_URL ?? ""); - return createClientFactory() - .use(authMiddleware(token)) - .create(definition, channel) as Client; -}; diff --git a/packages/zitadel-server/src/system/index.ts b/packages/zitadel-server/src/system/index.ts deleted file mode 100644 index 2217a9552..000000000 --- a/packages/zitadel-server/src/system/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./system"; diff --git a/packages/zitadel-server/src/system/system.ts b/packages/zitadel-server/src/system/system.ts deleted file mode 100644 index c5b77eac4..000000000 --- a/packages/zitadel-server/src/system/system.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; -import { importPKCS8, SignJWT } from "jose"; - -import { createChannel, createClientFactory } from "nice-grpc"; -import { - SystemServiceClient, - SystemServiceDefinition, -} from "../proto/server/zitadel/system"; -import { authMiddleware } from "../middleware"; - -const createSystemClient = ( - definition: CompatServiceDefinition, - accessToken: string -) => { - const channel = createChannel(process.env.ZITADEL_SYSTEM_API_URL ?? ""); - return createClientFactory() - .use(authMiddleware(accessToken)) - .create(definition, channel) as Client; -}; - -export const getSystem = async () => { - const token = await new SignJWT({}) - .setProtectedHeader({ alg: "RS256" }) - .setIssuedAt() - .setExpirationTime("1h") - .setIssuer(process.env.ZITADEL_SYSTEM_API_USERID ?? "") - .setSubject(process.env.ZITADEL_SYSTEM_API_USERID ?? "") - .setAudience(process.env.ZITADEL_ISSUER ?? "") - .sign(await importPKCS8(process.env.ZITADEL_SYSTEM_API_KEY ?? "", "RS256")); - - return createSystemClient( - SystemServiceDefinition as CompatServiceDefinition, - token - ); -}; diff --git a/packages/zitadel-server/src/v1.ts b/packages/zitadel-server/src/v1.ts new file mode 100644 index 000000000..f03a52e75 --- /dev/null +++ b/packages/zitadel-server/src/v1.ts @@ -0,0 +1,32 @@ +import { createClientFor } from "./server"; + +export { TextQueryMethod } from "./proto/server/zitadel/object"; + +import { + AdminServiceClient, + AdminServiceDefinition, +} from "./proto/server/zitadel/admin"; +import { + AuthServiceClient, + AuthServiceDefinition, +} from "./proto/server/zitadel/auth"; +import { + ManagementServiceClient, + ManagementServiceDefinition, +} from "./proto/server/zitadel/management"; +import { + SystemServiceClient, + SystemServiceDefinition, +} from "./proto/server/zitadel/system"; + +export const createAdminServiceClient = createClientFor( + AdminServiceDefinition +); +export const createAuthServiceClient = createClientFor( + AuthServiceDefinition +); +export const createManagementServiceClient = + createClientFor(ManagementServiceDefinition); +export const createSystemServiceClient = createClientFor( + SystemServiceDefinition +); diff --git a/packages/zitadel-server/src/v2/oidc/index.ts b/packages/zitadel-server/src/v2/oidc/index.ts deleted file mode 100644 index 11bff5c4c..000000000 --- a/packages/zitadel-server/src/v2/oidc/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./oidc"; -export * from "../../proto/server/zitadel/oidc/v2beta/oidc_service"; diff --git a/packages/zitadel-server/src/v2/oidc/oidc.ts b/packages/zitadel-server/src/v2/oidc/oidc.ts deleted file mode 100644 index cba72cda9..000000000 --- a/packages/zitadel-server/src/v2/oidc/oidc.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; - -import { ZitadelServer, createClient, getServers } from "../../server"; -import { OIDCServiceClient, OIDCServiceDefinition } from "."; - -export const getOidc = (server?: string | ZitadelServer) => { - let config; - if (server && typeof server === "string") { - const apps = getServers(); - config = apps.find((a) => a.name === server)?.config; - } else if (server && typeof server === "object") { - config = server.config; - } - - if (!config) { - throw Error("No ZITADEL server found"); - } - - return createClient( - OIDCServiceDefinition as CompatServiceDefinition, - config.apiUrl, - config.token - ); -}; diff --git a/packages/zitadel-server/src/v2/session/index.ts b/packages/zitadel-server/src/v2/session/index.ts deleted file mode 100644 index c11476a6c..000000000 --- a/packages/zitadel-server/src/v2/session/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./session"; -export * from "../../proto/server/zitadel/session/v2beta/session"; diff --git a/packages/zitadel-server/src/v2/session/session.ts b/packages/zitadel-server/src/v2/session/session.ts deleted file mode 100644 index 83acd2e38..000000000 --- a/packages/zitadel-server/src/v2/session/session.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; - -import { - SessionServiceClient, - SessionServiceDefinition, -} from "../../proto/server/zitadel/session/v2beta/session_service"; - -import { ZitadelServer, createClient, getServers } from "../../server"; - -export const getSession = (server?: string | ZitadelServer) => { - let config; - if (server && typeof server === "string") { - const apps = getServers(); - config = apps.find((a) => a.name === server)?.config; - } else if (server && typeof server === "object") { - config = server.config; - } - - if (!config) { - throw Error("No ZITADEL server found"); - } - - return createClient( - SessionServiceDefinition as CompatServiceDefinition, - config.apiUrl, - config.token - ); -}; diff --git a/packages/zitadel-server/src/v2/settings/index.ts b/packages/zitadel-server/src/v2/settings/index.ts deleted file mode 100644 index 7fdbfd0f9..000000000 --- a/packages/zitadel-server/src/v2/settings/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./settings"; -export * from "../../proto/server/zitadel/settings/v2beta/settings"; diff --git a/packages/zitadel-server/src/v2/settings/settings.ts b/packages/zitadel-server/src/v2/settings/settings.ts deleted file mode 100644 index 6c621253e..000000000 --- a/packages/zitadel-server/src/v2/settings/settings.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; - -import { - SettingsServiceClient, - SettingsServiceDefinition, -} from "../../proto/server/zitadel/settings/v2beta/settings_service"; - -import { ZitadelServer, createClient, getServers } from "../../server"; - -export const getSettings = (server?: string | ZitadelServer) => { - let config; - if (server && typeof server === "string") { - const apps = getServers(); - config = apps.find((a) => a.name === server)?.config; - } else if (server && typeof server === "object") { - config = server.config; - } - - if (!config) { - throw Error("No ZITADEL server found"); - } - - return createClient( - SettingsServiceDefinition as CompatServiceDefinition, - config.apiUrl, - config.token - ); -}; diff --git a/packages/zitadel-server/src/v2/user/index.ts b/packages/zitadel-server/src/v2/user/index.ts deleted file mode 100644 index 75d422bcf..000000000 --- a/packages/zitadel-server/src/v2/user/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./user"; -export * from "../../proto/server/zitadel/user/v2beta/user"; diff --git a/packages/zitadel-server/src/v2/user/user.ts b/packages/zitadel-server/src/v2/user/user.ts deleted file mode 100644 index d7f38cb2a..000000000 --- a/packages/zitadel-server/src/v2/user/user.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; - -import { - UserServiceClient, - UserServiceDefinition, -} from "../../proto/server/zitadel/user/v2beta/user_service"; - -import { ZitadelServer, createClient, getServers } from "../../server"; - -export const getUser = (server?: string | ZitadelServer) => { - let config; - if (server && typeof server === "string") { - const apps = getServers(); - config = apps.find((a) => a.name === server)?.config; - } else if (server && typeof server === "object") { - config = server.config; - } - - if (!config) { - throw Error("No ZITADEL server found"); - } - - return createClient( - UserServiceDefinition as CompatServiceDefinition, - config.apiUrl, - config.token - ); -}; diff --git a/packages/zitadel-server/src/v2beta.ts b/packages/zitadel-server/src/v2beta.ts new file mode 100644 index 000000000..dff3d0b6a --- /dev/null +++ b/packages/zitadel-server/src/v2beta.ts @@ -0,0 +1,61 @@ +import { createClientFor } from "./server"; + +export { TextQueryMethod } from "./proto/server/zitadel/object/v2beta/object"; +export { Prompt } from "./proto/server/zitadel/oidc/v2beta/authorization"; +export type { AuthRequest } from "./proto/server/zitadel/oidc/v2beta/authorization"; +export type { RegisterPasskeyResponse } from "./proto/server/zitadel/user/v2beta/user_service"; +export type { PasswordComplexitySettings } from "./proto/server/zitadel/settings/v2beta/password_settings"; +export type { + BrandingSettings, + Theme, +} from "./proto/server/zitadel/settings/v2beta/branding_settings"; +export type { LegalAndSupportSettings } from "./proto/server/zitadel/settings/v2beta/legal_settings"; +export type { + RequestChallenges, + Challenges, +} from "./proto/server/zitadel/session/v2beta/challenge"; +export type { Session } from "./proto/server/zitadel/session/v2beta/session"; + +export type { LoginSettings } from "./proto/server/zitadel/settings/v2beta/login_settings"; + +import { + UserServiceClient, + UserServiceDefinition, +} from "./proto/server/zitadel/user/v2beta/user_service"; +import { + SettingsServiceClient, + SettingsServiceDefinition, +} from "./proto/server/zitadel/settings/v2beta/settings_service"; +import { + SessionServiceClient, + SessionServiceDefinition, +} from "./proto/server/zitadel/session/v2beta/session_service"; +import { + OIDCServiceClient, + OIDCServiceDefinition, +} from "./proto/server/zitadel/oidc/v2beta/oidc_service"; +import { + OrganizationServiceClient, + OrganizationServiceDefinition, +} from "./proto/server/zitadel/org/v2beta/org_service"; +import { + FeatureServiceClient, + FeatureServiceDefinition, +} from "./proto/server/zitadel/feature/v2beta/feature_service"; + +export const createUserServiceClient = createClientFor( + UserServiceDefinition +); +export const createSettingsServiceClient = + createClientFor(SettingsServiceDefinition); +export const createSessionServiceClient = createClientFor( + SessionServiceDefinition +); +export const createOIDCServiceClient = createClientFor( + OIDCServiceDefinition +); +export const createOrganizationServiceClient = + createClientFor(OrganizationServiceDefinition); +export const createFeatureServiceClient = createClientFor( + FeatureServiceDefinition +); diff --git a/packages/zitadel-server/src/v3alpha.ts b/packages/zitadel-server/src/v3alpha.ts new file mode 100644 index 000000000..5eebd450d --- /dev/null +++ b/packages/zitadel-server/src/v3alpha.ts @@ -0,0 +1,22 @@ +import { createClientFor } from "./server"; + +import { + UserSchemaServiceClient, + UserSchemaServiceDefinition, +} from "./proto/server/zitadel/user/schema/v3alpha/user_schema_service"; +import { + UserServiceClient, + UserServiceDefinition, +} from "./proto/server/zitadel/user/v3alpha/user_service"; +import { + ExecutionServiceClient, + ExecutionServiceDefinition, +} from "./proto/server/zitadel/execution/v3alpha/execution_service"; + +export const createUserSchemaServiceClient = + createClientFor(UserSchemaServiceDefinition); +export const createUserServiceClient = createClientFor( + UserServiceDefinition +); +export const createExecutionServiceClient = + createClientFor(ExecutionServiceDefinition); diff --git a/packages/zitadel-server/tsup.config.ts b/packages/zitadel-server/tsup.config.ts index 2341f37cd..dbc25459e 100644 --- a/packages/zitadel-server/tsup.config.ts +++ b/packages/zitadel-server/tsup.config.ts @@ -1,13 +1,13 @@ import { defineConfig, Options } from "tsup"; export default defineConfig((options: Options) => ({ - treeshake: true, + treeshake: false, splitting: true, publicDir: true, - entry: ["src/index.ts", "src/**/index.ts"], + entry: ["src/index.ts", "src/v1.ts", "src/v2beta.ts", "src/v3alpha.ts"], format: ["esm", "cjs"], dts: true, - minify: true, + minify: false, clean: true, ...options, }));