diff --git a/.gitignore b/.gitignore index 2517f60c03b..a948c175525 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,5 @@ dist-ssr server/dist public/dist .turbo -packages/zitadel-core/src/app/proto +packages/zitadel-server/src/app/proto +packages/zitadel-client/src/app/proto diff --git a/README.md b/README.md index 2e29310023c..240bd8c27ba 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,9 @@ This Turborepo includes the following: ### Apps and Packages - `login`: The new login UI powered by Next.js -- `@zitadel/core`: core components for establishing client connection, grpc stub +- `@zitadel/server`: core components for establishing node client connection, grpc stub +- `@zitadel/client`: core components for establishing web client connection, grpc stub - `@zitadel/react`: shared React utilities and components - - `@zitadel/next`: shared Next.js utilities - `@zitadel/tsconfig`: shared `tsconfig.json`s used throughout the monorepo - `eslint-config-zitadel`: ESLint preset diff --git a/apps/login/lib/zitadel.ts b/apps/login/lib/zitadel.ts index 4bccc5d3036..2394e45af91 100644 --- a/apps/login/lib/zitadel.ts +++ b/apps/login/lib/zitadel.ts @@ -12,4 +12,4 @@ if (!getApps().length) { } const app = getApp(); -// const auth = getAuth(); +const auth = getAuth(); diff --git a/apps/login/package.json b/apps/login/package.json index 869db19b6e0..fe8e78e9391 100644 --- a/apps/login/package.json +++ b/apps/login/package.json @@ -17,7 +17,7 @@ "*": "prettier --write --ignore-unknown" }, "dependencies": { - "@zitadel/core": "workspace:*", + "@zitadel/server": "workspace:*", "@zitadel/react": "workspace:*", "@zitadel/next": "workspace:*", "@heroicons/react": "2.0.13", diff --git a/packages/zitadel-core/.eslintrc.js b/packages/zitadel-client/.eslintrc.js similarity index 100% rename from packages/zitadel-core/.eslintrc.js rename to packages/zitadel-client/.eslintrc.js diff --git a/packages/zitadel-core/.gitignore b/packages/zitadel-client/.gitignore similarity index 100% rename from packages/zitadel-core/.gitignore rename to packages/zitadel-client/.gitignore diff --git a/packages/zitadel-client/buf.gen.yaml b/packages/zitadel-client/buf.gen.yaml new file mode 100644 index 00000000000..6f34a51541c --- /dev/null +++ b/packages/zitadel-client/buf.gen.yaml @@ -0,0 +1,14 @@ +# buf.gen.yaml +version: v1 +managed: + enabled: true +plugins: + # - plugin: buf.build/protocolbuffers/js + # out: src/app/proto/generated + # opt: import_style=commonjs,binary + - plugin: buf.build/grpc/web + out: src/proto/client + opt: import_style=typescript,mode=grpcweb + # - plugin: buf.build/grpc-ecosystem/openapiv2 + # out: src/app/proto/generated + # opt: allow_delete_body diff --git a/packages/zitadel-core/package.json b/packages/zitadel-client/package.json similarity index 96% rename from packages/zitadel-core/package.json rename to packages/zitadel-client/package.json index fd4c2e1844d..be064b458d7 100644 --- a/packages/zitadel-core/package.json +++ b/packages/zitadel-client/package.json @@ -1,5 +1,5 @@ { - "name": "@zitadel/core", + "name": "@zitadel/client", "version": "0.0.0", "main": "./dist/index.js", "module": "./dist/index.mjs", diff --git a/packages/zitadel-core/src/admin.ts b/packages/zitadel-client/src/admin.ts similarity index 100% rename from packages/zitadel-core/src/admin.ts rename to packages/zitadel-client/src/admin.ts diff --git a/packages/zitadel-core/src/app.ts b/packages/zitadel-client/src/app.ts similarity index 100% rename from packages/zitadel-core/src/app.ts rename to packages/zitadel-client/src/app.ts diff --git a/packages/zitadel-core/src/auth.ts b/packages/zitadel-client/src/auth.ts similarity index 100% rename from packages/zitadel-core/src/auth.ts rename to packages/zitadel-client/src/auth.ts diff --git a/packages/zitadel-core/src/index.ts b/packages/zitadel-client/src/index.ts similarity index 100% rename from packages/zitadel-core/src/index.ts rename to packages/zitadel-client/src/index.ts diff --git a/packages/zitadel-core/src/management.ts b/packages/zitadel-client/src/management.ts similarity index 100% rename from packages/zitadel-core/src/management.ts rename to packages/zitadel-client/src/management.ts diff --git a/packages/zitadel-core/src/middleware.ts b/packages/zitadel-client/src/middleware.ts similarity index 100% rename from packages/zitadel-core/src/middleware.ts rename to packages/zitadel-client/src/middleware.ts diff --git a/packages/zitadel-core/src/system.ts b/packages/zitadel-client/src/system.ts similarity index 100% rename from packages/zitadel-core/src/system.ts rename to packages/zitadel-client/src/system.ts diff --git a/packages/zitadel-core/tsconfig.json b/packages/zitadel-client/tsconfig.json similarity index 100% rename from packages/zitadel-core/tsconfig.json rename to packages/zitadel-client/tsconfig.json diff --git a/packages/zitadel-server/.eslintrc.js b/packages/zitadel-server/.eslintrc.js new file mode 100644 index 00000000000..8e247ab3c27 --- /dev/null +++ b/packages/zitadel-server/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: ["zitadel"], +}; diff --git a/packages/zitadel-server/.gitignore b/packages/zitadel-server/.gitignore new file mode 100644 index 00000000000..c1aa2a7eb8b --- /dev/null +++ b/packages/zitadel-server/.gitignore @@ -0,0 +1 @@ +src/proto \ No newline at end of file diff --git a/packages/zitadel-core/buf.gen.yaml b/packages/zitadel-server/buf.gen.yaml similarity index 61% rename from packages/zitadel-core/buf.gen.yaml rename to packages/zitadel-server/buf.gen.yaml index a0a54c59150..0dbd909c23e 100644 --- a/packages/zitadel-core/buf.gen.yaml +++ b/packages/zitadel-server/buf.gen.yaml @@ -15,10 +15,4 @@ plugins: - useExactTypes=false # - plugin: buf.build/protocolbuffers/js # out: src/app/proto/generated - # opt: import_style=commonjs,binary - - plugin: buf.build/grpc/web - out: src/proto/client - opt: import_style=typescript,mode=grpcweb - # - plugin: buf.build/grpc-ecosystem/openapiv2 - # out: src/app/proto/generated - # opt: allow_delete_body + # opt: import_style=commonjs,binary \ No newline at end of file diff --git a/packages/zitadel-server/package.json b/packages/zitadel-server/package.json new file mode 100644 index 00000000000..46284111207 --- /dev/null +++ b/packages/zitadel-server/package.json @@ -0,0 +1,35 @@ +{ + "name": "@zitadel/server", + "version": "0.0.0", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "sideEffects": false, + "license": "MIT", + "files": [ + "dist/**" + ], + "scripts": { + "build": "tsup src/index.ts --format esm,cjs --dts", + "dev": "tsup src/index.ts --format esm,cjs --watch --dts", + "lint": "eslint \"src/**/*.ts*\"", + "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist", + "generate": "buf generate https://github.com/zitadel/zitadel.git --path ./proto/zitadel" + }, + "devDependencies": { + "@zitadel/tsconfig": "workspace:*", + "eslint": "^7.32.0", + "eslint-config-zitadel": "workspace:*", + "ts-proto": "^1.139.0", + "tsup": "^5.10.1", + "typescript": "^4.5.3" + }, + "publishConfig": { + "access": "public" + }, + "dependencies": { + "jose": "^4.13.1", + "nice-grpc": "2.0.1", + "protobufjs": "^7.2.3" + } +} diff --git a/packages/zitadel-server/src/admin.ts b/packages/zitadel-server/src/admin.ts new file mode 100644 index 00000000000..626a2b64545 --- /dev/null +++ b/packages/zitadel-server/src/admin.ts @@ -0,0 +1,28 @@ +import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; + +import { createChannel, createClientFactory } from "nice-grpc"; +import { + AuthServiceClient, + AuthServiceDefinition, +} from "./proto/server/zitadel/auth"; +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/app.ts b/packages/zitadel-server/src/app.ts new file mode 100644 index 00000000000..360518aab39 --- /dev/null +++ b/packages/zitadel-server/src/app.ts @@ -0,0 +1,45 @@ +/** + * Return a slugified copy of a string. + * + * @param {CoreProps} str The ZITADEL client configuration + * @return {Core} The client implementation. + */ + +let apps: ZitadelApp[] = []; + +export interface ZitadelCoreProps { + clientId: string; + apiUrl: string; // process.env.ZITADEL_API_URL + token: string; + adminToken?: string; + managementToken?: string; +} + +export interface ZitadelOptions extends ZitadelCoreProps { + name?: string; +} + +export interface ZitadelApp { + name: string | undefined; + config: ZitadelCoreProps; +} + +export async function initializeApp( + config: ZitadelCoreProps, + name?: string +): Promise { + const app = { config, name }; + return app; +} + +export function getApps(): ZitadelApp[] { + return apps; +} + +export function getApp(name?: string): ZitadelApp | undefined { + return name + ? apps.find((a) => a.name === name) + : apps.length === 1 + ? apps[0] + : undefined; +} diff --git a/packages/zitadel-server/src/auth.ts b/packages/zitadel-server/src/auth.ts new file mode 100644 index 00000000000..bab2f1cc974 --- /dev/null +++ b/packages/zitadel-server/src/auth.ts @@ -0,0 +1,25 @@ +import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions"; +import { createChannel, createClientFactory } from "nice-grpc"; +import { + AuthServiceClient, + AuthServiceDefinition, +} from "./proto/server/zitadel/auth"; +import { ZitadelApp } from "./app"; +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?: ZitadelApp): Promise { + return createClient( + AuthServiceDefinition as CompatServiceDefinition, + "" + ); +} diff --git a/packages/zitadel-server/src/index.ts b/packages/zitadel-server/src/index.ts new file mode 100644 index 00000000000..2d50c862b8b --- /dev/null +++ b/packages/zitadel-server/src/index.ts @@ -0,0 +1,8 @@ +export { initializeApp, getApps } from "./app"; + +export { getAuth } from "./auth"; +export { getManagement } from "./management"; +export { getAdmin } from "./admin"; +export { getSystem } from "./system"; + +export type { ZitadelOptions } from "./app"; diff --git a/packages/zitadel-server/src/management.ts b/packages/zitadel-server/src/management.ts new file mode 100644 index 00000000000..0d67c1224ca --- /dev/null +++ b/packages/zitadel-server/src/management.ts @@ -0,0 +1,45 @@ +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 { ZitadelApp, getApps } from "./app"; + +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 | ZitadelApp) => { + let config; + if (app && typeof app === "string") { + const apps = getApps(); + 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.ts b/packages/zitadel-server/src/middleware.ts new file mode 100644 index 00000000000..e88fd57cbe3 --- /dev/null +++ b/packages/zitadel-server/src/middleware.ts @@ -0,0 +1,14 @@ +import { CallOptions, ClientMiddlewareCall, Metadata } from "nice-grpc"; + +export const authMiddleware = (token: string) => + async function* ( + call: ClientMiddlewareCall, + options: CallOptions + ) { + if (!options.metadata?.has("authorization")) { + options.metadata ??= new Metadata(); + options.metadata?.set("authorization", `Bearer ${token}`); + } + + return yield* call.next(call.request, options); + }; diff --git a/packages/zitadel-server/src/system.ts b/packages/zitadel-server/src/system.ts new file mode 100644 index 00000000000..1a6ab7c58ff --- /dev/null +++ b/packages/zitadel-server/src/system.ts @@ -0,0 +1,35 @@ +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/tsconfig.json b/packages/zitadel-server/tsconfig.json new file mode 100644 index 00000000000..e502a91e183 --- /dev/null +++ b/packages/zitadel-server/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "@zitadel/tsconfig/node14.json", + "include": ["."], + "compilerOptions": { + "baseUrl": "." + }, + "exclude": ["dist", "build", "node_modules"] +}