Merge pull request #35 from zitadel/idp-register

IDP register
This commit is contained in:
Max Peintner
2023-08-03 13:09:03 +02:00
committed by GitHub
53 changed files with 2948 additions and 2182 deletions

View File

@@ -1,44 +0,0 @@
# name: Release
# on:
# push:
# branches:
# - main
# concurrency: ${{ github.workflow }}-${{ github.ref }}
# jobs:
# release:
# name: Release
# runs-on: ubuntu-latest
# steps:
# - name: Checkout Repo
# uses: actions/checkout@v2
# - name: Setup pnpm 7
# uses: pnpm/action-setup@v2
# with:
# version: 7
# - name: Setup Node.js 16.x
# uses: actions/setup-node@v2
# with:
# node-version: 16.x
# - name: Install Dependencies
# run: pnpm i
# - name: Create Release Pull Request or Publish to npm
# id: changesets
# uses: changesets/action@v1
# with:
# # This expects you to have a script called release which does a build for your packages and calls changeset publish
# publish: pnpm release
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# - name: Send a Slack notification if a publish happens
# if: steps.changesets.outputs.published == 'true'
# # You can do something when a publish happens.
# run: my-slack-bot send-notification --message "A new version of ${GITHUB_REPOSITORY} was published!"

View File

@@ -4,7 +4,6 @@ on: pull_request
jobs: jobs:
quality: quality:
name: Ensure Quality name: Ensure Quality
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -12,30 +11,29 @@ jobs:
timeout-minutes: 30 timeout-minutes: 30
permissions: permissions:
contents: 'read' contents: "read"
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
command: command:
- lint - lint
- test:unit - test:unit
- test:integration - test:integration
steps: steps:
- name: Checkout Repo - name: Checkout Repo
uses: actions/checkout@v2 uses: actions/checkout@v3
- name: Setup pnpm 7 - name: Setup pnpm 7
uses: pnpm/action-setup@v2 uses: pnpm/action-setup@v2
with: with:
version: 7 version: 7
- name: Setup Node.js 16.x - name: Setup Node.js 18.x
uses: actions/setup-node@v2 uses: actions/setup-node@v3
with: with:
node-version: 16.x node-version: 18.x
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v2
name: Install pnpm name: Install pnpm

2
.gitignore vendored
View File

@@ -17,3 +17,5 @@ packages/zitadel-server/src/app/proto
packages/zitadel-client/src/app/proto packages/zitadel-client/src/app/proto
.vscode .vscode
.idea .idea
.vercel
.env*.local

View File

@@ -0,0 +1,133 @@
import { ProviderSlug } from "#/lib/demos";
import { addHumanUser, server } from "#/lib/zitadel";
import Alert, { AlertType } from "#/ui/Alert";
import {
AddHumanUserRequest,
IDPInformation,
RetrieveIdentityProviderInformationResponse,
user,
IDPLink,
} from "@zitadel/server";
const PROVIDER_MAPPING: {
[provider: string]: (rI: IDPInformation) => Partial<AddHumanUserRequest>;
} = {
[ProviderSlug.GOOGLE]: (idp: IDPInformation) => {
const idpLink: IDPLink = {
idpId: idp.idpId,
userId: idp.userId,
userName: idp.userName,
};
const req: Partial<AddHumanUserRequest> = {
username: idp.userName,
email: {
email: idp.rawInformation?.User?.email,
isVerified: true,
},
// organisation: Organisation | undefined;
profile: {
displayName: idp.rawInformation?.User?.name ?? "",
firstName: idp.rawInformation?.User?.given_name ?? "",
lastName: idp.rawInformation?.User?.family_name ?? "",
},
idpLinks: [idpLink],
};
return req;
},
[ProviderSlug.GITHUB]: (idp: IDPInformation) => {
const idpLink: IDPLink = {
idpId: idp.idpId,
userId: idp.userId,
userName: idp.userName,
};
const req: Partial<AddHumanUserRequest> = {
username: idp.userName,
email: {
email: idp.rawInformation?.email,
isVerified: true,
},
// organisation: Organisation | undefined;
profile: {
displayName: idp.rawInformation?.name ?? "",
firstName: idp.rawInformation?.name ?? "",
lastName: idp.rawInformation?.name ?? "",
},
idpLinks: [idpLink],
};
return req;
},
};
function retrieveIDP(
id: string,
token: string
): Promise<IDPInformation | undefined> {
const userService = user.getUser(server);
return userService
.retrieveIdentityProviderInformation({ intentId: id, token: token }, {})
.then((resp: RetrieveIdentityProviderInformationResponse) => {
return resp.idpInformation;
});
}
function createUser(
provider: ProviderSlug,
info: IDPInformation
): Promise<string> {
const userData = PROVIDER_MAPPING[provider](info);
const userService = user.getUser(server);
return userService.addHumanUser(userData, {}).then((resp) => resp.userId);
}
export default async function Page({
searchParams,
params,
}: {
searchParams: Record<string | number | symbol, string | undefined>;
params: { provider: ProviderSlug };
}) {
const { id, token } = searchParams;
const { provider } = params;
if (provider && id && token) {
return retrieveIDP(id, token)
.then((information) => {
if (information) {
return createUser(provider, information).catch((error) => {
throw new Error(error.details);
});
} else {
throw new Error("Could not get user information.");
}
})
.then((userId) => {
return (
<div className="flex flex-col items-center space-y-4">
<h1>Register successful</h1>
<div>You have successfully been registered!</div>
</div>
);
})
.catch((error: Error) => {
return (
<div className="flex flex-col items-center space-y-4">
<h1>Register failed</h1>
<div className="w-full">
{
<Alert type={AlertType.ALERT}>
{JSON.stringify(error.message)}
</Alert>
}
</div>
</div>
);
});
} else {
return (
<div className="flex flex-col items-center space-y-4">
<h1>Register</h1>
<p className="ztdl-p">No id and token received!</p>
</div>
);
}
}

View File

@@ -0,0 +1,50 @@
import { getLegalAndSupportSettings, server } from "#/lib/zitadel";
import { SignInWithIDP } from "#/ui/SignInWithIDP";
import {
GetActiveIdentityProvidersResponse,
IdentityProvider,
ZitadelServer,
settings,
} from "@zitadel/server";
function getIdentityProviders(
server: ZitadelServer,
orgId?: string
): Promise<IdentityProvider[] | undefined> {
const settingsService = settings.getSettings(server);
return settingsService
.getActiveIdentityProviders(
orgId ? { ctx: { orgId } } : { ctx: { instance: true } },
{}
)
.then((resp: GetActiveIdentityProvidersResponse) => {
return resp.identityProviders;
});
}
export default async function Page() {
const legal = await getLegalAndSupportSettings(server);
// TODO if org idps should be shown replace emptystring with the orgId.
const identityProviders = await getIdentityProviders(server, "");
const host = process.env.VERCEL_URL
? `https://${process.env.VERCEL_URL}`
: "http://localhost:3000";
return (
<div className="flex flex-col items-center space-y-4">
<h1>Register</h1>
<p className="ztdl-p">
Select one of the following providers to register
</p>
{legal && identityProviders && process.env.ZITADEL_API_URL && (
<SignInWithIDP
host={host}
identityProviders={identityProviders}
></SignInWithIDP>
)}
</div>
);
}

View File

@@ -0,0 +1,19 @@
import { server, startIdentityProviderFlow } from "#/lib/zitadel";
import { NextRequest, NextResponse } from "next/server";
export async function POST(request: NextRequest) {
const body = await request.json();
if (body) {
let { idpId, successUrl, failureUrl } = body;
return startIdentityProviderFlow(server, { idpId, successUrl, failureUrl })
.then((resp) => {
return NextResponse.json(resp);
})
.catch((error) => {
return NextResponse.json(error, { status: 500 });
});
} else {
return NextResponse.json({}, { status: 400 });
}
}

View File

@@ -8,6 +8,7 @@ import ThemeWrapper from "#/ui/ThemeWrapper";
import { getBrandingSettings } from "#/lib/zitadel"; import { getBrandingSettings } from "#/lib/zitadel";
import { server } from "../lib/zitadel"; import { server } from "../lib/zitadel";
import { BrandingSettings } from "@zitadel/server"; import { BrandingSettings } from "@zitadel/server";
import ThemeProvider from "#/ui/ThemeProvider";
const lato = Lato({ const lato = Lato({
weight: ["400", "700", "900"], weight: ["400", "700", "900"],
@@ -41,29 +42,31 @@ export default async function RootLayout({
<head /> <head />
<body> <body>
<ThemeWrapper branding={partial}> <ThemeWrapper branding={partial}>
<LayoutProviders> <ThemeProvider>
<div className="h-screen overflow-y-scroll bg-background-light-600 dark:bg-background-dark-600 bg-[url('/grid-light.svg')] dark:bg-[url('/grid-dark.svg')]"> <LayoutProviders>
{showNav && <GlobalNav />} <div className="h-screen overflow-y-scroll bg-background-light-600 dark:bg-background-dark-600 bg-[url('/grid-light.svg')] dark:bg-[url('/grid-dark.svg')]">
{showNav && <GlobalNav />}
<div className={`${showNav ? "lg:pl-72" : ""} pb-4`}> <div className={`${showNav ? "lg:pl-72" : ""} pb-4`}>
<div className="mx-auto max-w-[440px] space-y-8 pt-20 lg:py-8"> <div className="mx-auto max-w-[440px] space-y-8 pt-20 lg:py-8">
{showNav && ( {showNav && (
<div className="rounded-lg bg-vc-border-gradient dark:bg-dark-vc-border-gradient p-px shadow-lg shadow-black/5 dark:shadow-black/20"> <div className="rounded-lg bg-vc-border-gradient dark:bg-dark-vc-border-gradient p-px shadow-lg shadow-black/5 dark:shadow-black/20">
<div className="rounded-lg bg-background-light-400 dark:bg-background-dark-500"> <div className="rounded-lg bg-background-light-400 dark:bg-background-dark-500">
<AddressBar domain={domain} /> <AddressBar domain={domain} />
</div>
</div> </div>
</div> )}
)}
<div className="rounded-lg bg-vc-border-gradient dark:bg-dark-vc-border-gradient p-px shadow-lg shadow-black/5 dark:shadow-black/20 mb-10"> <div className="rounded-lg bg-vc-border-gradient dark:bg-dark-vc-border-gradient p-px shadow-lg shadow-black/5 dark:shadow-black/20 mb-10">
<div className="rounded-lg bg-background-light-400 dark:bg-background-dark-500 px-8 py-12"> <div className="rounded-lg bg-background-light-400 dark:bg-background-dark-500 px-8 py-12">
{children} {children}
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </LayoutProviders>
</LayoutProviders> </ThemeProvider>
</ThemeWrapper> </ThemeWrapper>
<Analytics /> <Analytics />
</body> </body>

View File

@@ -0,0 +1,21 @@
import { stub } from "../support/mock";
const IDP_URL = "https://example.com/idp/url";
describe("register idps", () => {
beforeEach(() => {
stub("zitadel.user.v2alpha.UserService", "StartIdentityProviderFlow", {
data: {
authUrl: IDP_URL,
},
});
});
it("should redirect the user to the correct url", () => {
cy.visit("/register/idp");
cy.get('button[e2e="google"]').click();
cy.origin(IDP_URL, { args: IDP_URL }, (url) => {
cy.location("href", { timeout: 10_000 }).should("eq", url);
});
});
});

View File

@@ -4,6 +4,11 @@ export type Item = {
description?: string; description?: string;
}; };
export enum ProviderSlug {
GOOGLE = "google",
GITHUB = "github",
}
export const demos: { name: string; items: Item[] }[] = [ export const demos: { name: string; items: Item[] }[] = [
{ {
name: "Login", name: "Login",
@@ -38,6 +43,11 @@ export const demos: { name: string; items: Item[] }[] = [
slug: "register", slug: "register",
description: "Create your ZITADEL account", description: "Create your ZITADEL account",
}, },
{
name: "IDP Register",
slug: "register/idp",
description: "Register with an Identity Provider",
},
{ {
name: "Verify email", name: "Verify email",
slug: "verify", slug: "verify",

View File

@@ -25,6 +25,10 @@ import {
LoginSettings, LoginSettings,
GetLoginSettingsResponse, GetLoginSettingsResponse,
ListAuthenticationMethodTypesResponse, ListAuthenticationMethodTypesResponse,
StartIdentityProviderFlowRequest,
StartIdentityProviderFlowResponse,
RetrieveIdentityProviderInformationRequest,
RetrieveIdentityProviderInformationResponse,
} from "@zitadel/server"; } from "@zitadel/server";
export const zitadelConfig: ZitadelServerOptions = { export const zitadelConfig: ZitadelServerOptions = {
@@ -173,14 +177,14 @@ export async function addHumanUser(
server: ZitadelServer, server: ZitadelServer,
{ email, firstName, lastName, password }: AddHumanUserData { email, firstName, lastName, password }: AddHumanUserData
): Promise<string> { ): Promise<string> {
const mgmt = user.getUser(server); const userService = user.getUser(server);
const payload = { const payload = {
email: { email }, email: { email },
username: email, username: email,
profile: { firstName, lastName }, profile: { firstName, lastName },
}; };
return mgmt return userService
.addHumanUser( .addHumanUser(
password password
? { ? {
@@ -195,6 +199,31 @@ export async function addHumanUser(
}); });
} }
export async function startIdentityProviderFlow(
server: ZitadelServer,
{ idpId, successUrl, failureUrl }: StartIdentityProviderFlowRequest
): Promise<StartIdentityProviderFlowResponse> {
const userService = user.getUser(server);
return userService.startIdentityProviderFlow({
idpId,
successUrl,
failureUrl,
});
}
export async function retrieveIdentityProviderInformation(
server: ZitadelServer,
{ intentId, token }: RetrieveIdentityProviderInformationRequest
): Promise<RetrieveIdentityProviderInformationResponse> {
const userService = user.getUser(server);
return userService.retrieveIdentityProviderInformation({
intentId,
token,
});
}
export async function verifyEmail( export async function verifyEmail(
server: ZitadelServer, server: ZitadelServer,
userId: string, userId: string,

View File

@@ -17,6 +17,21 @@
} }
} }
}, },
{
"service": "zitadel.settings.v2alpha.SettingsService",
"method": "GetActiveIdentityProviders",
"out": {
"data": {
"identityProviders": [
{
"id": "123",
"name": "Hubba bubba",
"type": 10
}
]
}
}
},
{ {
"service": "zitadel.settings.v2alpha.SettingsService", "service": "zitadel.settings.v2alpha.SettingsService",
"method": "GetPasswordComplexitySettings", "method": "GetPasswordComplexitySettings",

View File

@@ -36,13 +36,13 @@
"@heroicons/react": "2.0.13", "@heroicons/react": "2.0.13",
"@tailwindcss/forms": "0.5.3", "@tailwindcss/forms": "0.5.3",
"@vercel/analytics": "^1.0.0", "@vercel/analytics": "^1.0.0",
"@zitadel/next": "workspace:*", "@zitadel/client": "workspace:*",
"@zitadel/react": "workspace:*", "@zitadel/react": "workspace:*",
"@zitadel/server": "workspace:*", "@zitadel/server": "workspace:*",
"clsx": "1.2.1", "clsx": "1.2.1",
"date-fns": "2.29.3", "date-fns": "2.29.3",
"moment": "^2.29.4", "moment": "^2.29.4",
"next": "13.4.7", "next": "13.4.12",
"next-themes": "^0.2.1", "next-themes": "^0.2.1",
"nice-grpc": "2.0.1", "nice-grpc": "2.0.1",
"react": "18.2.0", "react": "18.2.0",

View File

@@ -13,7 +13,7 @@
} }
.ztdl-p { .ztdl-p {
@apply text-sm; @apply text-sm text-text-light-secondary-500 dark:text-text-dark-secondary-500;
} }
} }

View File

@@ -11,7 +11,7 @@ export function AddressBar({ domain }: Props) {
const pathname = usePathname(); const pathname = usePathname();
return ( return (
<div className="flex items-center space-x-2 p-3.5 lg:px-5 lg:py-3"> <div className="flex items-center space-x-2 p-3.5 lg:px-5 lg:py-3 overflow-hidden">
<div className="text-gray-600"> <div className="text-gray-600">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@@ -27,8 +27,8 @@ export function AddressBar({ domain }: Props) {
</svg> </svg>
</div> </div>
<div className="flex space-x-1 text-sm font-medium"> <div className="flex space-x-1 text-sm font-medium">
<div> <div className="max-w-[150px] px-2 overflow-hidden text-gray-500 text-ellipsis">
<span className="px-2 text-gray-500">{domain}</span> <span className="whitespace-nowrap">{domain}</span>
</div> </div>
{pathname ? ( {pathname ? (
<> <>

View File

@@ -2,6 +2,7 @@ import clsx from "clsx";
import React, { import React, {
ButtonHTMLAttributes, ButtonHTMLAttributes,
DetailedHTMLProps, DetailedHTMLProps,
ReactNode,
forwardRef, forwardRef,
} from "react"; } from "react";
@@ -65,16 +66,14 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
...props ...props
}, },
ref ref
) => { ) => (
return ( <button
<button type="button"
type="button" ref={ref}
ref={ref} className={`${getButtonClasses(size, variant, color)} ${className}`}
className={`${getButtonClasses(size, variant, color)} ${className}`} {...props}
{...props} >
> {children}
{children} </button>
</button> )
);
}
); );

View File

@@ -1,10 +0,0 @@
import { SignInWithGoogle, SignInWithGitlab } from "@zitadel/react";
export default function IdentityProviders() {
return (
<div className="space-y-4 py-4">
<SignInWithGoogle />
<SignInWithGitlab />
</div>
);
}

View File

@@ -1,28 +1,18 @@
"use client"; "use client";
import { ZitadelReactProvider } from "@zitadel/react";
import { ThemeProvider, useTheme } from "next-themes"; import { useTheme } from "next-themes";
type Props = { type Props = {
children: React.ReactNode; children: React.ReactNode;
}; };
export function LayoutProviders({ children }: Props) { export function LayoutProviders({ children }: Props) {
// const { resolvedTheme } = useTheme(); const { resolvedTheme } = useTheme();
const isDark = false; //resolvedTheme && resolvedTheme === "dark"; const isDark = resolvedTheme === "dark";
// useEffect(() => {
// console.log("layoutproviders useeffect");
// setTheme(document);
// });
return ( return (
<ThemeProvider <div className={`${isDark ? "ui-dark" : "ui-light"} `}>
attribute="class" <ZitadelReactProvider dark={isDark}>{children}</ZitadelReactProvider>
defaultTheme="system" </div>
storageKey="cp-theme"
value={{ dark: "dark" }}
>
<div className={`${isDark ? "ui-dark" : "ui-light"} `}>{children}</div>
</ThemeProvider>
); );
} }

View File

@@ -0,0 +1,132 @@
"use client";
import { ReactNode, useState } from "react";
import {
SignInWithGitlab,
SignInWithAzureAD,
SignInWithGoogle,
SignInWithGithub,
} from "@zitadel/react";
import { useRouter } from "next/navigation";
import { ProviderSlug } from "#/lib/demos";
import Alert from "./Alert";
export interface SignInWithIDPProps {
children?: ReactNode;
host: string;
identityProviders: any[];
startIDPFlowPath?: (idpId: string) => string;
}
const START_IDP_FLOW_PATH = (idpId: string) =>
`/v2alpha/users/idps/${idpId}/start`;
export function SignInWithIDP({
host,
identityProviders,
startIDPFlowPath = START_IDP_FLOW_PATH,
}: SignInWithIDPProps) {
const [loading, setLoading] = useState<boolean>(false);
const [error, setError] = useState<string>("");
const router = useRouter();
async function startFlow(idpId: string, provider: ProviderSlug) {
setLoading(true);
const res = await fetch("/api/idp/start", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
idpId,
successUrl: `${host}/register/idp/${provider}/success`,
failureUrl: `${host}/register/idp/${provider}/failure`,
}),
});
const response = await res.json();
setLoading(false);
if (!res.ok) {
setError(response.details);
return Promise.reject(response.details);
}
return response;
}
return (
<div className="flex flex-col w-full space-y-2 text-sm">
{identityProviders &&
identityProviders.map((idp, i) => {
switch (idp.type) {
case 6: // IdentityProviderType.IDENTITY_PROVIDER_TYPE_GITHUB:
return (
<SignInWithGithub
key={`idp-${i}`}
onClick={() =>
startFlow(idp.id, ProviderSlug.GITHUB).then(
({ authUrl }) => {
router.push(authUrl);
}
)
}
></SignInWithGithub>
);
case 7: // IdentityProviderType.IDENTITY_PROVIDER_TYPE_GITHUB_ES:
return (
<SignInWithGithub
key={`idp-${i}`}
onClick={() => alert("TODO: unimplemented")}
></SignInWithGithub>
);
case 5: // IdentityProviderType.IDENTITY_PROVIDER_TYPE_AZURE_AD:
return (
<SignInWithAzureAD
key={`idp-${i}`}
onClick={() => alert("TODO: unimplemented")}
></SignInWithAzureAD>
);
case 10: // IdentityProviderType.IDENTITY_PROVIDER_TYPE_GOOGLE:
return (
<SignInWithGoogle
key={`idp-${i}`}
e2e="google"
name={idp.name}
onClick={() =>
startFlow(idp.id, ProviderSlug.GOOGLE).then(
({ authUrl }) => {
router.push(authUrl);
}
)
}
></SignInWithGoogle>
);
case 8: // IdentityProviderType.IDENTITY_PROVIDER_TYPE_GITLAB:
return (
<SignInWithGitlab
key={`idp-${i}`}
onClick={() => alert("TODO: unimplemented")}
></SignInWithGitlab>
);
case 9: //IdentityProviderType.IDENTITY_PROVIDER_TYPE_GITLAB_SELF_HOSTED:
return (
<SignInWithGitlab
key={`idp-${i}`}
onClick={() => alert("TODO: unimplemented")}
></SignInWithGitlab>
);
default:
return null;
}
})}
{error && (
<div className="py-4">
<Alert>{error}</Alert>
</div>
)}
</div>
);
}
SignInWithIDP.displayName = "SignInWithIDP";

View File

@@ -0,0 +1,16 @@
"use client";
import { ThemeProvider as ThemeP } from "next-themes";
import { ReactNode } from "react";
export default function ThemeProvider({ children }: { children: ReactNode }) {
return (
<ThemeP
attribute="class"
defaultTheme="system"
storageKey="cp-theme"
value={{ dark: "dark" }}
>
{children}
</ThemeP>
);
}

View File

@@ -21,7 +21,7 @@
"eslint": "^7.32.0", "eslint": "^7.32.0",
"eslint-config-zitadel": "workspace:*", "eslint-config-zitadel": "workspace:*",
"prettier": "^2.5.1", "prettier": "^2.5.1",
"turbo": "^1.10.3" "turbo": "^1.10.8"
}, },
"packageManager": "pnpm@7.15.0" "packageManager": "pnpm@7.15.0"
} }

View File

@@ -11,12 +11,12 @@
], ],
"scripts": { "scripts": {
"generate": "buf generate https://github.com/zitadel/zitadel.git --path ./proto/zitadel", "generate": "buf generate https://github.com/zitadel/zitadel.git --path ./proto/zitadel",
"build": "tsup src/index.ts --format esm,cjs --dts", "build": "tsup --dts",
"test": "pnpm test:unit", "test": "pnpm test:unit",
"test:watch": "pnpm test:unit:watch", "test:watch": "pnpm test:unit:watch",
"test:unit": "jest", "test:unit": "jest",
"test:unit:watch": "jest --watch", "test:unit:watch": "jest --watch",
"dev": "tsup src/index.ts --format esm,cjs --watch --dts", "dev": "tsup --watch --dts",
"lint": "eslint \"src/**/*.ts*\"", "lint": "eslint \"src/**/*.ts*\"",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist" "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
}, },
@@ -41,4 +41,4 @@
"nice-grpc-web": "^3.2.3", "nice-grpc-web": "^3.2.3",
"protobufjs": "^7.2.3" "protobufjs": "^7.2.3"
} }
} }

View File

@@ -0,0 +1,13 @@
import { defineConfig, Options } from "tsup";
export default defineConfig((options: Options) => ({
treeshake: true,
splitting: true,
publicDir: true,
entry: ["src/index.ts", "src/**/index.ts"],
format: ["esm", "cjs"],
dts: true,
minify: true,
clean: true,
...options,
}));

View File

@@ -10,17 +10,18 @@
"dist/**" "dist/**"
], ],
"scripts": { "scripts": {
"build": "tsup src/index.tsx --format esm,cjs --dts --external react", "build": "tsup",
"test": "pnpm test:unit", "test": "pnpm test:unit",
"test:watch": "pnpm test:unit:watch", "test:watch": "pnpm test:unit:watch",
"test:unit": "jest", "test:unit": "jest --passWithNoTests",
"test:unit:watch": "jest --watch", "test:unit:watch": "jest --watch",
"dev": "tsup src/index.tsx --format esm,cjs --watch --dts --external react", "dev": "tsup --watch",
"lint": "eslint \"src/**/*.ts*\"", "lint": "eslint \"src/**/*.ts*\"",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist" "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.1", "@types/jest": "^29.5.1",
"@types/react": "^17.0.13",
"@zitadel/tsconfig": "workspace:*", "@zitadel/tsconfig": "workspace:*",
"eslint": "^7.32.0", "eslint": "^7.32.0",
"eslint-config-zitadel": "workspace:*", "eslint-config-zitadel": "workspace:*",
@@ -28,12 +29,22 @@
"ts-jest": "^29.1.0", "ts-jest": "^29.1.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tsup": "^5.10.1", "tsup": "^5.10.1",
"typescript": "^4.9.3" "typescript": "^4.9.3",
"tailwindcss": "3.2.4",
"postcss": "8.4.21",
"zitadel-tailwind-config": "workspace:*",
"@zitadel/server": "workspace:*"
}, },
"peerDependencies": { "peerDependencies": {
"next": "^13" "@zitadel/react": "workspace:*",
"@zitadel/server": "workspace:*",
"next": "^13",
"react": "18.2.0"
}, },
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
},
"dependencies": {
"next": "^13.4.10"
} }
} }

View File

@@ -0,0 +1,9 @@
// If you want to use other PostCSS plugins, see the following:
// https://tailwindcss.com/docs/using-with-preprocessors
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};

View File

@@ -1,9 +1,9 @@
export type ZitadelUIProps = { export type ZitadelNextProps = {
dark: boolean; dark: boolean;
children: React.ReactNode; children: React.ReactNode;
}; };
export function ZitadelUIProvider({ dark, children }: ZitadelUIProps) { export function ZitadelNextProvider({ dark, children }: ZitadelNextProps) {
return ( return (
<div className={`${dark ? "ztdl-dark" : "ztdl-light"} `}>{children}</div> <div className={`${dark ? "ztdl-dark" : "ztdl-light"} `}>{children}</div>
); );

View File

@@ -1,5 +0,0 @@
describe('slug', () => {
it('this is not a real test', () => { })
})
export { }

View File

@@ -1 +1,6 @@
export { toSlug } from "./toSlug"; import "./styles.css";
export {
ZitadelNextProvider,
type ZitadelNextProps,
} from "./components/ZitadelNextProvider";

View File

@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@@ -1,10 +0,0 @@
/**
* Return a slugified copy of a string.
*
* @param {string} str The string to be slugified
* @return {string} The slugified string.
*/
export function toSlug(str: string): string {
let s = str;
return s;
}

View File

@@ -0,0 +1,9 @@
const sharedConfig = require("zitadel-tailwind-config/tailwind.config.js");
/** @type {import('tailwindcss').Config} */
module.exports = {
presets: [sharedConfig],
prefix: "ztdl-next-",
darkMode: "class",
content: [`src/**/*.{js,ts,jsx,tsx}`],
};

View File

@@ -0,0 +1,12 @@
{
"extends": ["//"],
"pipeline": {
"dev": {
"dependsOn": ["@zitadel/react#build"]
},
"build": {
"outputs": ["dist/**"],
"dependsOn": ["@zitadel/react#build", "@zitadel/server#build"]
}
}
}

View File

@@ -12,7 +12,7 @@
"./assets/*": "./dist/assets/*" "./assets/*": "./dist/assets/*"
}, },
"scripts": { "scripts": {
"build": "tsup", "build": "tsup src/index.tsx --format esm,cjs --dts --external react",
"test": "pnpm test:unit", "test": "pnpm test:unit",
"test:watch": "pnpm test:unit:watch", "test:watch": "pnpm test:unit:watch",
"test:unit": "jest", "test:unit": "jest",
@@ -26,8 +26,8 @@
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^14.0.0", "@testing-library/react": "^14.0.0",
"@types/jest": "^29.5.1", "@types/jest": "^29.5.1",
"@types/react": "^17.0.13", "@types/react": "^18.2.17",
"@types/react-dom": "^17.0.8", "@types/react-dom": "^18.2.7",
"@types/testing-library__jest-dom": "^5.14.6", "@types/testing-library__jest-dom": "^5.14.6",
"@zitadel/tsconfig": "workspace:*", "@zitadel/tsconfig": "workspace:*",
"autoprefixer": "10.4.13", "autoprefixer": "10.4.13",
@@ -40,8 +40,8 @@
"tailwindcss": "3.2.4", "tailwindcss": "3.2.4",
"ts-jest": "^29.1.0", "ts-jest": "^29.1.0",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"tsup": "^5.10.1", "tsup": "^7.1.0",
"typescript": "^4.9.3", "typescript": "^5.1.6",
"zitadel-tailwind-config": "workspace:*" "zitadel-tailwind-config": "workspace:*"
}, },
"publishConfig": { "publishConfig": {
@@ -50,4 +50,4 @@
"peerDependencies": { "peerDependencies": {
"react": "18.2.0" "react": "18.2.0"
} }
} }

View File

@@ -0,0 +1,9 @@
import { ButtonHTMLAttributes, DetailedHTMLProps } from "react";
export type SignInWithIdentityProviderProps = DetailedHTMLProps<
ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
> & {
name?: string;
e2e?: string;
};

View File

@@ -0,0 +1,42 @@
"use client";
import { ReactNode, forwardRef } from "react";
import { SignInWithIdentityProviderProps } from "./SignInWith";
export const SignInWithAzureAD = forwardRef<
HTMLButtonElement,
SignInWithIdentityProviderProps
>(
({ children, className = "", name = "", ...props }, ref): ReactNode => (
<button
type="button"
ref={ref}
className={`ztdl-w-full ztdl-cursor-pointer ztdl-flex ztdl-flex-row ztdl-items-center ztdl-bg-white ztdl-text-black dark:ztdl-bg-transparent dark:ztdl-text-white border ztdl-border-divider-light dark:ztdl-border-divider-dark rounded-md px-4 text-sm ${className}`}
{...props}
>
<div className="ztdl-h-12 ztdl-p-[10px] ztdl-w-12 ztdl-flex ztdl-items-center ztdl-justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="21"
height="21"
viewBox="0 0 21 21"
className="w-full h-full"
>
<path fill="#f25022" d="M1 1H10V10H1z"></path>
<path fill="#00a4ef" d="M1 11H10V20H1z"></path>
<path fill="#7fba00" d="M11 1H20V10H11z"></path>
<path fill="#ffb900" d="M11 11H20V20H11z"></path>
</svg>
</div>
{children ? (
children
) : (
<span className="ztdl-ml-4">
{name ? name : "Sign in with AzureAD"}
</span>
)}
</button>
)
);
SignInWithAzureAD.displayName = "SignInWithAzureAD";

View File

@@ -0,0 +1,58 @@
"use client";
import { ReactNode, forwardRef } from "react";
import { SignInWithIdentityProviderProps } from "./SignInWith";
export const SignInWithGithub = forwardRef<
HTMLButtonElement,
SignInWithIdentityProviderProps
>(
({ children, className = "", name = "", ...props }, ref): ReactNode => (
<button
type="button"
ref={ref}
className={`ztdl-h-[50px] ztdl-w-full ztdl-cursor-pointer ztdl-flex ztdl-flex-row ztdl-items-center ztdl-bg-white ztdl-text-black dark:ztdl-bg-transparent dark:ztdl-text-white border ztdl-border-divider-light dark:ztdl-border-divider-dark rounded-md px-4 text-sm ${className}`}
{...props}
>
<div className="ztdl-h-8 ztdl-w-8 ztdl-mx-2 flex items-center justify-center">
<svg
xmlns="http://www.w3.org/2000/svg"
width="1024"
height="1024"
fill="none"
viewBox="0 0 1024 1024"
className="hidden dark:ztdl-block"
>
<path
fill="#fafafa"
fillRule="evenodd"
d="M512 0C229.12 0 0 229.12 0 512c0 226.56 146.56 417.92 350.08 485.76 25.6 4.48 35.2-10.88 35.2-24.32 0-12.16-.64-52.48-.64-95.36-128.64 23.68-161.92-31.36-172.16-60.16-5.76-14.72-30.72-60.16-52.48-72.32-17.92-9.6-43.52-33.28-.64-33.92 40.32-.64 69.12 37.12 78.72 52.48 46.08 77.44 119.68 55.68 149.12 42.24 4.48-33.28 17.92-55.68 32.64-68.48-113.92-12.8-232.96-56.96-232.96-252.8 0-55.68 19.84-101.76 52.48-137.6-5.12-12.8-23.04-65.28 5.12-135.68 0 0 42.88-13.44 140.8 52.48 40.96-11.52 84.48-17.28 128-17.28 43.52 0 87.04 5.76 128 17.28 97.92-66.56 140.8-52.48 140.8-52.48 28.16 70.4 10.24 122.88 5.12 135.68 32.64 35.84 52.48 81.28 52.48 137.6 0 196.48-119.68 240-233.6 252.8 18.56 16 34.56 46.72 34.56 94.72 0 68.48-.64 123.52-.64 140.8 0 13.44 9.6 29.44 35.2 24.32C877.44 929.92 1024 737.92 1024 512 1024 229.12 794.88 0 512 0z"
clipRule="evenodd"
></path>
</svg>
<svg
xmlns="http://www.w3.org/2000/svg"
width="1024"
height="1024"
fill="none"
viewBox="0 0 1024 1024"
className="ztdl-block dark:ztdl-hidden"
>
<path
fill="#1B1F23"
fillRule="evenodd"
d="M512 0C229.12 0 0 229.12 0 512c0 226.56 146.56 417.92 350.08 485.76 25.6 4.48 35.2-10.88 35.2-24.32 0-12.16-.64-52.48-.64-95.36-128.64 23.68-161.92-31.36-172.16-60.16-5.76-14.72-30.72-60.16-52.48-72.32-17.92-9.6-43.52-33.28-.64-33.92 40.32-.64 69.12 37.12 78.72 52.48 46.08 77.44 119.68 55.68 149.12 42.24 4.48-33.28 17.92-55.68 32.64-68.48-113.92-12.8-232.96-56.96-232.96-252.8 0-55.68 19.84-101.76 52.48-137.6-5.12-12.8-23.04-65.28 5.12-135.68 0 0 42.88-13.44 140.8 52.48 40.96-11.52 84.48-17.28 128-17.28 43.52 0 87.04 5.76 128 17.28 97.92-66.56 140.8-52.48 140.8-52.48 28.16 70.4 10.24 122.88 5.12 135.68 32.64 35.84 52.48 81.28 52.48 137.6 0 196.48-119.68 240-233.6 252.8 18.56 16 34.56 46.72 34.56 94.72 0 68.48-.64 123.52-.64 140.8 0 13.44 9.6 29.44 35.2 24.32C877.44 929.92 1024 737.92 1024 512 1024 229.12 794.88 0 512 0z"
clipRule="evenodd"
></path>
</svg>
</div>
{children ? (
children
) : (
<span className="ztdl-ml-4">{name ? name : "Sign in with GitHub"}</span>
)}
</button>
)
);
SignInWithGithub.displayName = "SignInWithGithub";

View File

@@ -1,15 +1,21 @@
import { render, screen } from '@testing-library/react'; import { render, screen } from "@testing-library/react";
import { SignInWithGoogle } from './SignInWithGoogle'; import { SignInWithGitlab } from "./SignInWithGitlab";
describe('<SignInWithGoogle />', () => { describe("<SignInWithGitlab />", () => {
it('renders without crashing', () => { it("renders without crashing", () => {
const { container } = render(<SignInWithGoogle />); const { container } = render(<SignInWithGitlab />);
expect(container.firstChild).toBeDefined(); expect(container.firstChild).toBeDefined();
}); });
it('displays the correct text', () => { it("displays the default text", () => {
render(<SignInWithGoogle />); render(<SignInWithGitlab />);
const signInText = screen.getByText(/Sign in with Google/i); const signInText = screen.getByText(/Sign in with Gitlab/i);
expect(signInText).toBeInTheDocument(); expect(signInText).toBeInTheDocument();
}); });
});
it("displays the given text", () => {
render(<SignInWithGitlab name={"Gitlab"} />);
const signInText = screen.getByText(/Gitlab/i);
expect(signInText).toBeInTheDocument();
});
});

View File

@@ -1,19 +1,23 @@
import * as React from "react"; import { ReactNode, forwardRef } from "react";
import { SignInWithIdentityProviderProps } from "./SignInWith";
export interface SignInWithGitlabProps { export const SignInWithGitlab = forwardRef<
children?: React.ReactNode; HTMLButtonElement,
} SignInWithIdentityProviderProps
>(
export function SignInWithGitlab(props: SignInWithGitlabProps) { ({ children, className = "", name = "", ...props }, ref): ReactNode => (
return ( <button
<div className="ztdl-cursor-pointer ztdl-flex ztdl-flex-row ztdl-items-center ztdl-bg-white ztdl-text-black dark:ztdl-bg-transparent dark:ztdl-text-white border ztdl-border-divider-light dark:ztdl-border-divider-dark rounded-md px-4 text-sm"> type="button"
ref={ref}
className={`ztdl-w-full ztdl-cursor-pointer ztdl-flex ztdl-flex-row ztdl-items-center ztdl-bg-white ztdl-text-black dark:ztdl-bg-transparent dark:ztdl-text-white border ztdl-border-divider-light dark:ztdl-border-divider-dark rounded-md px-4 text-sm ${className}`}
{...props}
>
<div className="ztdl-h-12 ztdl-w-12 flex items-center justify-center"> <div className="ztdl-h-12 ztdl-w-12 flex items-center justify-center">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
width={25} width={25}
height={24} height={24}
fill="none" fill="none"
{...props}
> >
<path <path
fill="#e24329" fill="#e24329"
@@ -33,9 +37,13 @@ export function SignInWithGitlab(props: SignInWithGitlabProps) {
/> />
</svg> </svg>
</div> </div>
<span className="ztdl-ml-4">Sign in with Gitlab</span> {children ? (
</div> children
); ) : (
} <span className="ztdl-ml-4">{name ? name : "Sign in with GitLab"}</span>
)}
</button>
)
);
SignInWithGitlab.displayName = "SignInWithGitlab"; SignInWithGitlab.displayName = "SignInWithGitlab";

View File

@@ -1,15 +1,21 @@
import { render, screen } from '@testing-library/react'; import { render, screen } from "@testing-library/react";
import { SignInWithGitlab } from './SignInWithGitlab'; import { SignInWithGoogle } from "./SignInWithGoogle";
describe('<SignInWithGitlab />', () => { describe("<SignInWithGoogle />", () => {
it('renders without crashing', () => { it("renders without crashing", () => {
const { container } = render(<SignInWithGitlab />); const { container } = render(<SignInWithGoogle />);
expect(container.firstChild).toBeDefined(); expect(container.firstChild).toBeDefined();
}); });
it('displays the correct text', () => { it("displays the default text", () => {
render(<SignInWithGitlab />); render(<SignInWithGoogle />);
const signInText = screen.getByText(/Sign in with Gitlab/i); const signInText = screen.getByText(/Sign in with Google/i);
expect(signInText).toBeInTheDocument(); expect(signInText).toBeInTheDocument();
}); });
});
it("displays the given text", () => {
render(<SignInWithGoogle name={"Google"} />);
const signInText = screen.getByText(/Google/i);
expect(signInText).toBeInTheDocument();
});
});

View File

@@ -1,22 +1,23 @@
import * as React from "react"; import { ReactNode, forwardRef } from "react";
import { SignInWithIdentityProviderProps } from "./SignInWith";
export interface SignInWithGoogleProps { export const SignInWithGoogle = forwardRef<
children?: React.ReactNode; HTMLButtonElement,
} SignInWithIdentityProviderProps
>(
export function SignInWithGoogle(props: SignInWithGoogleProps) { ({ children, className = "", name = "", ...props }, ref): ReactNode => (
return ( <button
<div className="ztdl-cursor-pointer ztdl-flex ztdl-flex-row ztdl-items-center ztdl-bg-white ztdl-text-black dark:ztdl-bg-transparent dark:ztdl-text-white border ztdl-border-divider-light dark:ztdl-border-divider-dark rounded-md px-4 text-sm"> type="button"
ref={ref}
className={`ztdl-w-full ztdl-cursor-pointer ztdl-flex ztdl-flex-row ztdl-items-center ztdl-bg-white ztdl-text-black dark:ztdl-bg-transparent dark:ztdl-text-white border ztdl-border-divider-light dark:ztdl-border-divider-dark rounded-md px-4 text-sm ${className}`}
{...props}
>
<div className="ztdl-h-12 ztdl-w-12 ztdl-flex ztdl-items-center ztdl-justify-center"> <div className="ztdl-h-12 ztdl-w-12 ztdl-flex ztdl-items-center ztdl-justify-center">
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
xmlSpace="preserve" xmlSpace="preserve"
id="Capa_1" id="Capa_1"
// style={{
// enableBackground: "new 0 0 150 150",
// }}
viewBox="0 0 150 150" viewBox="0 0 150 150"
{...props}
> >
<style> <style>
{ {
@@ -49,9 +50,13 @@ export function SignInWithGoogle(props: SignInWithGoogleProps) {
/> />
</svg> </svg>
</div> </div>
<span className="ztdl-ml-4">Sign in with Google</span> {children ? (
</div> children
); ) : (
} <span className="ztdl-ml-4">{name ? name : "Sign in with Google"}</span>
)}
</button>
)
);
SignInWithGoogle.displayName = "SignInWithGoogle"; SignInWithGoogle.displayName = "SignInWithGoogle";

View File

@@ -0,0 +1,17 @@
import * as React from "react";
export interface SignInWithIDPProps {
children?: React.ReactNode;
orgId?: string;
}
export function SignInWithIDP(props: SignInWithIDPProps) {
return (
<div className="ztdl-flex ztdl-flex-row border ztdl-border-divider-light dark:ztdl-border-divider-dark rounded-md px-4 text-sm">
<div></div>
{props.children}
</div>
);
}
SignInWithIDP.displayName = "SignInWithIDP";

View File

@@ -0,0 +1,10 @@
export type ZitadelReactProps = {
dark: boolean;
children: React.ReactNode;
};
export function ZitadelReactProvider({ dark, children }: ZitadelReactProps) {
return (
<div className={`${dark ? "ztdl-dark" : "ztdl-light"} `}>{children}</div>
);
}

View File

@@ -1,16 +1,19 @@
import "./styles.css"; import "./styles.css";
export { export { SignInWithGoogle } from "./components/SignInWithGoogle";
SignInWithGoogle,
type SignInWithGoogleProps, export { SignInWithGitlab } from "./components/SignInWithGitlab";
} from "./components/SignInWithGoogle";
export { SignInWithAzureAD } from "./components/SignInWithAzureAD";
export { SignInWithGithub } from "./components/SignInWithGithub";
export { export {
SignInWithGitlab, ZitadelReactProvider,
type SignInWithGitlabProps, type ZitadelReactProps,
} from "./components/SignInWithGitlab"; } from "./components/ZitadelReactProvider";
export { export {
ZitadelUIProvider, SignInWithIDP,
type ZitadelUIProps, type SignInWithIDPProps,
} from "./components/ZitadelUIProvider"; } from "./components/SignInWithIDP";

View File

@@ -1,3 +0,0 @@
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z" transform="scale(64)" fill="#fafafa"/>
</svg>

Before

Width:  |  Height:  |  Size: 968 B

View File

@@ -1,3 +0,0 @@
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z" transform="scale(64)" fill="#1B1F23"/>
</svg>

Before

Width:  |  Height:  |  Size: 968 B

View File

@@ -1 +0,0 @@
<svg width="25" height="24" viewBox="0 0 25 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="m24.507 9.5-.034-.09L21.082.562a.896.896.0 00-1.694.091l-2.29 7.01H7.825L5.535.653A.898.898.0 003.841.563L.451 9.411.416 9.5a6.297 6.297.0 002.09 7.278l.012.01.03.022 5.16 3.867 2.56 1.935 1.554 1.176a1.051 1.051.0 001.268.0l1.555-1.176 2.56-1.935 5.197-3.89.014-.01A6.297 6.297.0 0024.507 9.5z" fill="#e24329"/><path d="m24.507 9.5-.034-.09a11.44 11.44.0 00-4.56 2.051l-7.447 5.632 4.742 3.584 5.197-3.89.014-.01A6.297 6.297.0 0024.507 9.5z" fill="#fc6d26"/><path d="m7.707 20.677 2.56 1.935 1.555 1.176a1.051 1.051.0 001.268.0l1.555-1.176 2.56-1.935-4.743-3.584-4.755 3.584z" fill="#fca326"/><path d="M5.01 11.461A11.43 11.43.0 00.45 9.411L.416 9.5a6.297 6.297.0 002.09 7.278l.012.01.03.022 5.16 3.867 4.745-3.584-7.444-5.632z" fill="#fc6d26"/></svg>

Before

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="21" viewBox="0 0 21 21"><title>MS-SymbolLockup</title><rect x="1" y="1" width="9" height="9" fill="#f25022"/><rect x="1" y="11" width="9" height="9" fill="#00a4ef"/><rect x="11" y="1" width="9" height="9" fill="#7fba00"/><rect x="11" y="11" width="9" height="9" fill="#ffb900"/></svg>

Before

Width:  |  Height:  |  Size: 343 B

View File

@@ -1,61 +0,0 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14576) -->
<svg xmlns="http://www.w3.org/2000/svg" version="1.0" x="0px" y="0px" width="598.48541" height="599.83948" viewBox="0 0 598.486 671.089" enable-background="new 0 0 598.486 671.089">
<g transform="translate(0,35.625)">
<path fill="#fff" d="M 277.7249,0.87048682 C 410.2899,-8.3215132 498.1879,56.550487 548.4459,135.58949 C 573.6459,175.21949 598.3709,235.40949 598.4849,297.25249 C 598.6069,364.44649 576.8389,422.63549 548.4459,465.33049 C 519.2639,509.21349 481.5199,545.45849 434.2559,569.25749 C 355.2499,609.04049 244.8359,610.12849 172.5149,571.82349 C 91.972897,529.16549 30.046897,468.27849 7.0028967,362.68749 C -2.2191033,320.43149 -3.2791033,265.83249 9.5688967,218.98749 C 12.583897,207.99849 18.062897,196.43349 22.399897,185.62849 C 43.241897,133.70449 78.716897,88.552487 122.4769,57.323487 C 140.0609,44.775487 161.3929,32.295487 180.2139,23.964487 C 203.6319,13.599487 243.0599,3.2734868 277.7249,0.87048682 z" />
<path fill="#000" d="M 529.1839,304.72449 C 529.1839,430.01249 427.6179,531.57149 302.3319,531.57149 C 177.0459,531.57149 75.481897,430.01249 75.481897,304.72449 C 75.481897,179.43949 177.0459,77.872487 302.3319,77.872487 C 427.6169,77.872487 529.1839,179.43949 529.1839,304.72449 z" />
<path fill="#000" d="M 277.7249,0.87048682 C 410.2899,-8.3215132 498.1879,56.550487 548.4459,135.58949 C 573.6459,175.21949 598.3709,235.40949 598.4849,297.25249 C 598.6069,364.44649 576.8389,422.63549 548.4459,465.33049 C 519.2639,509.21349 481.5199,545.45849 434.2559,569.25749 C 355.2499,609.04049 244.8359,610.12849 172.5149,571.82349 C 91.972897,529.16549 30.046897,468.27849 7.0028967,362.68749 C -2.2191033,320.43149 -3.2791033,265.83249 9.5688967,218.98749 C 12.583897,207.99849 18.062897,196.43349 22.399897,185.62849 C 43.241897,133.70449 78.716897,88.552487 122.4769,57.323487 C 140.0609,44.775487 161.3929,32.295487 180.2139,23.964487 C 203.6319,13.599487 243.0599,3.2734868 277.7249,0.87048682 z M 232.8179,22.682487 C 183.5789,35.448487 147.4759,58.319487 116.0619,82.985487 C 70.762897,118.55349 41.884897,168.18849 24.965897,227.96849 C 6.1428967,294.47649 18.233897,374.95849 44.211897,425.55649 C 71.150897,478.02849 107.3219,518.75949 158.4019,547.44549 C 208.0969,575.35349 277.9929,593.27349 350.8589,579.52149 C 415.5989,567.30349 464.7679,539.10049 504.8239,497.40649 C 558.4159,441.62149 601.4889,338.87249 572.8259,230.53449 C 565.1639,201.57949 555.1469,171.40149 539.4659,145.85349 C 530.9939,132.05149 518.5619,118.47349 506.1069,104.79649 C 459.1009,53.175487 383.1279,8.6924868 285.4229,14.983487 C 266.8289,16.180487 250.4879,18.100487 232.8179,22.682487 z" />
<g style="fill:none;stroke:#fff;stroke-width:2" id="hashpattern">
<g>
<line y2="314.658" x2="578.188" y1="576.79" x1="316.05"/>
<line y2="292.754" x2="556.415" y1="556.03" x1="293.134"/>
<line y2="270.851" x2="534.643" y1="535.273" x1="270.217"/>
<line y2="248.948" x2="512.87" y1="514.513" x1="247.3"/>
<line y2="227.044" x2="491.098" y1="493.754" x1="224.384"/>
<line y2="205.141" x2="469.324" y1="473" x1="201.467"/>
<line y2="183.238" x2="447.552" y1="452.236" x1="178.55"/>
<line y2="161.334" x2="425.778" y1="431.477" x1="155.633"/>
<line y2="139.431" x2="404" y1="410.718" x1="132.716"/>
<line y2="117.528" x2="382.233" y1="389.958" x1="109.8"/>
<line y2="95.625" x2="360.46" y1="369.2" x1="86.883"/>
<line y2="73.721" x2="338.688" y1="348.441" x1="63.966"/>
<line y2="51.818" x2="316.915" y1="327.681" x1="41.049"/>
<line y2="29.915" x2="295.142" y1="306.922" x1="18.132"/>
</g>
<g>
<line y2="576.96" x2="285.419" y1="309.572" x1="18.043" />
<line y2="555.488" x2="307.622" y1="287.579" x1="39.726" />
<line y2="534.014" x2="329.825" y1="265.586" x1="61.409" />
<line y2="512.542" x2="352.029" y1="243.593" x1="83.092" />
<line y2="491.068" x2="374.231" y1="221.6" x1="104.774"/>
<line y2="469.595" x2="396.436" y1="199.607" x1="126.457"/>
<line y2="448.122" x2="418.639" y1="177.614" x1="148.14" />
<line y2="426.648" x2="440.842" y1="155.621" x1="169.822"/>
<line y2="405.175" x2="463.046" y1="133.628" x1="191.505"/>
<line y2="383.7" x2="485.248" y1="111.635" x1="213.188"/>
<line y2="362.229" x2="507.452" y1="89.642" x1="234.871"/>
<line y2="340.755" x2="529.655" y1="67.649" x1="256.553"/>
<line y2="319.283" x2="551.858" y1="45.657" x1="278.236"/>
<line y2="297.809" x2="574.062" y1="23.664" x1="299.92" />
</g>
</g>
<path d="M 490.7099,106.07949 C 467.1169,82.486487 438.1109,61.226487 403.4629,48.342487 C 367.5489,34.987487 326.9229,23.730487 279.0079,27.813487 C 202.6819,34.319487 149.0919,68.564487 108.3629,108.64549 C 79.834897,136.71849 58.375897,171.11949 44.210897,211.28849 C 23.412897,270.26949 24.674897,339.88649 48.059897,399.89549 C 68.006897,451.08249 100.6549,492.36849 146.8539,524.35049 C 190.2849,554.41749 252.6189,577.73649 322.6299,571.82349 C 407.9019,564.62149 470.2939,520.87349 511.2369,470.46349 C 521.7129,457.56749 532.1289,442.99049 538.1799,425.55749 C 544.1089,412.99649 547.0109,404.45749 549.7279,399.89649 C 561.0999,374.41449 567.1249,347.52849 568.9729,317.78249 C 574.6579,226.29049 539.4559,154.82649 490.7099,106.07949 z M 465.5789,384.82749 C 465.4159,385.17549 465.2699,385.49949 465.0999,385.85849 C 460.8699,397.96349 453.5829,408.08549 446.2589,417.04149 C 417.6249,452.04549 373.9959,482.42349 314.3639,487.42549 C 265.4029,491.52949 221.8119,475.33849 191.4409,454.46049 C 165.0489,436.31749 144.9869,413.85949 130.9189,386.86949 C 130.0609,385.24549 121.8909,366.42249 121.8669,365.59449 C 110.7219,331.02549 109.7549,275.43949 121.1939,242.08249 C 128.8279,219.81949 141.5509,195.73149 158.4019,176.64749 C 181.6679,150.29649 204.9509,133.41149 241.7999,121.47649 C 258.6249,116.02649 273.6869,110.47949 294.4039,109.92949 C 344.9239,108.58449 396.3689,131.26749 423.9909,156.11849 C 449.3749,178.95549 478.3049,223.44049 485.5779,265.17649 C 493.0629,308.13349 485.0749,350.07449 465.5789,384.82749 z" />
<path stroke="#000" stroke-width="6" fill="#fff" d="M 377.768,426.033 C 365.328,426.033 354.411,418.155 350.601,406.429 L 336.745,364.211 L 267.43,364.211 L 254.556,406.044 C 250.67,417.998 239.67,426 227.166,426 C 224.164,426 221.182,425.525 218.303,424.591 C 203.357,420.104 194.872,404.017 199.451,388.751 L 257.957,203.428 C 261.756,191.639 272.94,183.416 285.157,183.416 L 316.267,183.416 C 328.553,183.416 339.736,191.499 343.461,203.073 L 404.99,388.327 C 409.91,403.473 401.763,419.732 386.839,424.59 C 383.888,425.548 380.837,426.033 377.768,426.033 L 377.768,426.033 z" />
<g id="OAUTH" fill="#fff">
<g>
<path d="M 148.001,124.354 L 147.928,124.255 C 140.632,114.256 142.773,100.268 153.518,92.426 C 164.263,84.585 178.066,86.786 185.362,96.784 L 185.435,96.883 C 192.731,106.882 190.59,120.871 179.845,128.712 C 169.1,136.553 155.297,134.353 148.001,124.354 z M 175.658,104.171 L 175.585,104.072 C 171.919,99.048 165.093,97.32 159.771,101.204 C 154.498,105.052 154.088,111.907 157.754,116.932 L 157.827,117.031 C 161.494,122.055 168.319,123.783 173.592,119.935 C 178.915,116.051 179.325,109.196 175.658,104.171 z" />
<path d="M 218.344,58.817 L 229.309,55.299 L 260.048,91.033 L 247.851,94.946 L 242.509,88.576 L 226.676,93.656 L 226.096,101.927 L 214.134,105.765 L 218.344,58.817 z M 236.384,80.775 L 228.066,70.573 L 227.177,83.729 L 236.384,80.775 z" />
<path d="M 279.795,69.567 L 279.891,45.364 L 292.023,45.412 L 291.928,69.369 C 291.903,75.589 295.032,78.557 299.836,78.577 C 304.64,78.596 307.792,75.776 307.815,69.741 L 307.912,45.477 L 320.044,45.525 L 319.949,69.42 C 319.894,83.338 311.926,89.404 299.67,89.355 C 287.415,89.305 279.742,83.054 279.795,69.567 z" />
<path d="M 363.859,65.338 L 351.491,61.563 L 354.547,51.55 L 390.71,62.587 L 387.654,72.6 L 375.286,68.826 L 365.759,100.042 L 354.333,96.555 L 363.859,65.338 z" />
<path d="M 423.012,76.559 L 432.958,83.178 L 424.02,96.61 L 436.786,105.106 L 445.725,91.673 L 455.671,98.292 L 431.788,134.181 L 421.841,127.562 L 430.917,113.924 L 418.15,105.428 L 409.075,119.066 L 399.129,112.447 L 423.012,76.559 z"/>
</g>
<g>
<path d="M 458.146,468.883 L 458.222,468.98 C 465.896,478.693 464.29,492.755 453.852,501.001 C 443.414,509.247 429.536,507.575 421.862,497.862 L 421.786,497.765 C 414.112,488.051 415.719,473.99 426.156,465.744 C 436.594,457.499 450.472,459.17 458.146,468.883 z M 431.277,490.11 L 431.353,490.207 C 435.209,495.088 442.096,496.554 447.267,492.469 C 452.389,488.422 452.538,481.556 448.681,476.675 L 448.605,476.578 C 444.75,471.697 437.862,470.231 432.74,474.278 C 427.569,478.363 427.421,485.229 431.277,490.11 z"/>
<path d="M 390.707,537.182 L 379.907,541.179 L 347.625,506.833 L 359.638,502.386 L 365.256,508.516 L 380.85,502.744 L 381.065,494.456 L 392.847,490.095 L 390.707,537.182 z M 371.718,516.04 L 380.477,525.865 L 380.786,512.683 L 371.718,516.04 z"/>
<path d="M 328.888,528.985 L 329.955,553.164 L 317.835,553.699 L 316.778,529.766 C 316.504,523.552 313.236,520.738 308.437,520.95 C 303.638,521.162 300.625,524.131 300.891,530.16 L 301.961,554.4 L 289.841,554.935 L 288.787,531.064 C 288.173,517.16 295.841,510.718 308.084,510.178 C 320.328,509.637 328.293,515.511 328.888,528.985 z"/>
<path d="M 244.671,536.891 L 257.158,540.262 L 254.429,550.37 L 217.918,540.515 L 220.647,530.406 L 233.134,533.777 L 241.641,502.261 L 253.177,505.375 L 244.671,536.891 z"/>
<path d="M 185.65,528.108 L 175.401,521.966 L 183.696,508.125 L 170.543,500.241 L 162.248,514.082 L 152,507.94 L 174.164,470.961 L 184.412,477.104 L 175.99,491.156 L 189.144,499.04 L 197.566,484.988 L 207.814,491.131 L 185.65,528.108 z"/>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 9.6 KiB

View File

@@ -1,12 +1,8 @@
{ {
"extends": [ "extends": ["//"],
"//"
],
"pipeline": { "pipeline": {
"build": { "build": {
"outputs": [ "outputs": ["dist/**"]
"dist/**"
]
} }
} }
} }

View File

@@ -12,7 +12,11 @@ export {
Theme, Theme,
} from "./proto/server/zitadel/settings/v2alpha/branding_settings"; } from "./proto/server/zitadel/settings/v2alpha/branding_settings";
export { LoginSettings } from "./proto/server/zitadel/settings/v2alpha/login_settings"; export {
LoginSettings,
IdentityProvider,
IdentityProviderType,
} from "./proto/server/zitadel/settings/v2alpha/login_settings";
export { export {
ChallengeKind, ChallengeKind,
@@ -24,6 +28,10 @@ export {
Session, Session,
Factors, Factors,
} from "./proto/server/zitadel/session/v2alpha/session"; } from "./proto/server/zitadel/session/v2alpha/session";
export {
IDPInformation,
IDPLink,
} from "./proto/server/zitadel/user/v2alpha/idp";
export { export {
ListSessionsResponse, ListSessionsResponse,
GetSessionResponse, GetSessionResponse,
@@ -38,9 +46,12 @@ export {
GetGeneralSettingsResponse, GetGeneralSettingsResponse,
GetLoginSettingsResponse, GetLoginSettingsResponse,
GetLoginSettingsRequest, GetLoginSettingsRequest,
GetActiveIdentityProvidersResponse,
GetActiveIdentityProvidersRequest,
} from "./proto/server/zitadel/settings/v2alpha/settings_service"; } from "./proto/server/zitadel/settings/v2alpha/settings_service";
export { export {
AddHumanUserResponse, AddHumanUserResponse,
AddHumanUserRequest,
VerifyEmailResponse, VerifyEmailResponse,
VerifyPasskeyRegistrationRequest, VerifyPasskeyRegistrationRequest,
VerifyPasskeyRegistrationResponse, VerifyPasskeyRegistrationResponse,
@@ -51,11 +62,16 @@ export {
ListAuthenticationMethodTypesResponse, ListAuthenticationMethodTypesResponse,
ListAuthenticationMethodTypesRequest, ListAuthenticationMethodTypesRequest,
AuthenticationMethodType, AuthenticationMethodType,
StartIdentityProviderFlowRequest,
StartIdentityProviderFlowResponse,
RetrieveIdentityProviderInformationRequest,
RetrieveIdentityProviderInformationResponse,
} from "./proto/server/zitadel/user/v2alpha/user_service"; } from "./proto/server/zitadel/user/v2alpha/user_service";
export { export {
SetHumanPasswordResponse, SetHumanPasswordResponse,
SetHumanPasswordRequest, SetHumanPasswordRequest,
} from "./proto/server/zitadel/management"; } from "./proto/server/zitadel/management";
export * from "./proto/server/zitadel/idp";
export { type LegalAndSupportSettings } from "./proto/server/zitadel/settings/v2alpha/legal_settings"; export { type LegalAndSupportSettings } from "./proto/server/zitadel/settings/v2alpha/legal_settings";
export { type PasswordComplexitySettings } from "./proto/server/zitadel/settings/v2alpha/password_settings"; export { type PasswordComplexitySettings } from "./proto/server/zitadel/settings/v2alpha/password_settings";
export { type ResourceOwnerType } from "./proto/server/zitadel/settings/v2alpha/settings"; export { type ResourceOwnerType } from "./proto/server/zitadel/settings/v2alpha/settings";

4018
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -21,9 +21,7 @@
"cache": false "cache": false
} }
}, },
"globalDependencies": [ "globalDependencies": ["**/.env.*local"],
"**/.env.*local"
],
"globalEnv": [ "globalEnv": [
"ZITADEL_API_URL", "ZITADEL_API_URL",
"ZITADEL_SERVICE_USER_TOKEN", "ZITADEL_SERVICE_USER_TOKEN",
@@ -31,6 +29,7 @@
"ZITADEL_SYSTEM_API_USERID", "ZITADEL_SYSTEM_API_USERID",
"ZITADEL_SYSTEM_API_KEY", "ZITADEL_SYSTEM_API_KEY",
"ZITADEL_ISSUER", "ZITADEL_ISSUER",
"ZITADEL_ADMIN_TOKEN" "ZITADEL_ADMIN_TOKEN",
"VERCEL_URL"
] ]
} }