mirror of
https://github.com/zitadel/zitadel.git
synced 2025-12-12 05:06:55 +00:00
session service, username, password form
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
import { Button, ButtonVariants } from "#/ui/Button";
|
import { Button, ButtonVariants } from "#/ui/Button";
|
||||||
import { NextPage, NextPageContext } from "next";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useSearchParams } from "next/navigation";
|
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
searchParams: { [key: string]: string | string[] | undefined };
|
searchParams: { [key: string]: string | string[] | undefined };
|
||||||
|
|||||||
@@ -2,41 +2,15 @@
|
|||||||
|
|
||||||
import { Button, ButtonVariants } from "#/ui/Button";
|
import { Button, ButtonVariants } from "#/ui/Button";
|
||||||
import IdentityProviders from "#/ui/IdentityProviders";
|
import IdentityProviders from "#/ui/IdentityProviders";
|
||||||
import { TextInput } from "#/ui/Input";
|
import UsernameForm from "#/ui/UsernameForm";
|
||||||
import { useRouter } from "next/navigation";
|
|
||||||
|
|
||||||
export default function Page() {
|
export default function Page() {
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
function submit() {
|
|
||||||
router.push("/password");
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>Welcome back!</h1>
|
<h1>Welcome back!</h1>
|
||||||
<p className="ztdl-p">Enter your login data.</p>
|
<p className="ztdl-p">Enter your login data.</p>
|
||||||
|
|
||||||
<form className="w-full" onSubmit={() => submit()}>
|
<UsernameForm />
|
||||||
<div className="block">
|
|
||||||
<TextInput label="Loginname" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<IdentityProviders />
|
|
||||||
</div>
|
|
||||||
<div className="mt-8 flex w-full flex-row items-center justify-between">
|
|
||||||
<Button type="button" variant={ButtonVariants.Secondary}>
|
|
||||||
back
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
variant={ButtonVariants.Primary}
|
|
||||||
onClick={() => submit()}
|
|
||||||
>
|
|
||||||
continue
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import { Analytics } from "@vercel/analytics/react";
|
|||||||
import ThemeWrapper from "#/ui/ThemeWrapper";
|
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 { LabelPolicyColors } from "#/utils/colors";
|
import { BrandingSettings } from "@zitadel/server";
|
||||||
|
|
||||||
const lato = Lato({
|
const lato = Lato({
|
||||||
weight: ["400", "700", "900"],
|
weight: ["400", "700", "900"],
|
||||||
@@ -25,26 +25,20 @@ export default async function RootLayout({
|
|||||||
// later only shown with dev mode enabled
|
// later only shown with dev mode enabled
|
||||||
const showNav = true;
|
const showNav = true;
|
||||||
|
|
||||||
const branding = await getBrandingSettings(server);
|
// const general = await getGeneralSettings(server);
|
||||||
let partialPolicy: LabelPolicyColors | undefined;
|
const branding: BrandingSettings = await getBrandingSettings(server);
|
||||||
console.log(branding);
|
let partial: Partial<BrandingSettings> | undefined;
|
||||||
if (branding) {
|
if (branding) {
|
||||||
partialPolicy = {
|
partial = {
|
||||||
backgroundColor: branding?.backgroundColor,
|
lightTheme: branding?.lightTheme,
|
||||||
backgroundColorDark: branding?.backgroundColorDark,
|
darkTheme: branding?.darkTheme,
|
||||||
primaryColor: branding?.primaryColor,
|
|
||||||
primaryColorDark: branding?.primaryColorDark,
|
|
||||||
warnColor: branding?.warnColor,
|
|
||||||
warnColorDark: branding?.warnColorDark,
|
|
||||||
fontColor: branding?.fontColor,
|
|
||||||
fontColorDark: branding?.fontColorDark,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<html lang="en" className={`${lato.className}`} suppressHydrationWarning>
|
<html lang="en" className={`${lato.className}`} suppressHydrationWarning>
|
||||||
<head />
|
<head />
|
||||||
<body>
|
<body>
|
||||||
<ThemeWrapper branding={partialPolicy}>
|
<ThemeWrapper branding={partial}>
|
||||||
<LayoutProviders>
|
<LayoutProviders>
|
||||||
<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')]">
|
<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 />}
|
{showNav && <GlobalNav />}
|
||||||
|
|||||||
26
apps/login/app/session/route.ts
Normal file
26
apps/login/app/session/route.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { createSession, server, setSession } from "#/lib/zitadel";
|
||||||
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
|
||||||
|
export async function POST(request: NextRequest) {
|
||||||
|
const body = await request.json();
|
||||||
|
if (body) {
|
||||||
|
const { loginName } = body;
|
||||||
|
|
||||||
|
const session = await createSession(server, loginName);
|
||||||
|
return NextResponse.json(session);
|
||||||
|
} else {
|
||||||
|
return NextResponse.error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PUT(request: NextRequest) {
|
||||||
|
const body = await request.json();
|
||||||
|
if (body) {
|
||||||
|
const { loginName } = body;
|
||||||
|
|
||||||
|
const session = await setSession(server, loginName);
|
||||||
|
return NextResponse.json(session);
|
||||||
|
} else {
|
||||||
|
return NextResponse.error();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,12 @@
|
|||||||
import {
|
import {
|
||||||
management,
|
|
||||||
ZitadelServer,
|
ZitadelServer,
|
||||||
ZitadelServerOptions,
|
ZitadelServerOptions,
|
||||||
orgMetadata,
|
management,
|
||||||
getServer,
|
settings,
|
||||||
getServers,
|
getServers,
|
||||||
initializeServer,
|
initializeServer,
|
||||||
settings,
|
session,
|
||||||
} from "@zitadel/server";
|
} from "@zitadel/server";
|
||||||
// import { getAuth } from "@zitadel/server/auth";
|
|
||||||
|
|
||||||
export const zitadelConfig: ZitadelServerOptions = {
|
export const zitadelConfig: ZitadelServerOptions = {
|
||||||
name: "zitadel login",
|
name: "zitadel login",
|
||||||
@@ -38,6 +36,21 @@ export function getBrandingSettings(
|
|||||||
.then((resp) => resp.settings);
|
.then((resp) => resp.settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getGeneralSettings(
|
||||||
|
server: ZitadelServer
|
||||||
|
): Promise<any | undefined> {
|
||||||
|
// settings.branding_settings.BrandingSettings
|
||||||
|
const settingsService = settings.getSettings(server);
|
||||||
|
return settingsService
|
||||||
|
.getGeneralSettings(
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
// metadata: orgMetadata(process.env.ZITADEL_ORG_ID ?? "")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((resp) => resp.supportedLanguages);
|
||||||
|
}
|
||||||
|
|
||||||
export function getLegalAndSupportSettings(
|
export function getLegalAndSupportSettings(
|
||||||
server: ZitadelServer
|
server: ZitadelServer
|
||||||
): Promise<any | undefined> {
|
): Promise<any | undefined> {
|
||||||
@@ -56,6 +69,7 @@ export function getPasswordComplexitySettings(
|
|||||||
server: ZitadelServer
|
server: ZitadelServer
|
||||||
): Promise<any | undefined> {
|
): Promise<any | undefined> {
|
||||||
const settingsService = settings.getSettings(server);
|
const settingsService = settings.getSettings(server);
|
||||||
|
|
||||||
return settingsService
|
return settingsService
|
||||||
.getPasswordComplexitySettings(
|
.getPasswordComplexitySettings(
|
||||||
{},
|
{},
|
||||||
@@ -66,6 +80,22 @@ export function getPasswordComplexitySettings(
|
|||||||
.then((resp) => resp.settings);
|
.then((resp) => resp.settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function createSession(
|
||||||
|
server: ZitadelServer,
|
||||||
|
loginName: string
|
||||||
|
): Promise<any | undefined> {
|
||||||
|
const sessionService = session.getSession(server);
|
||||||
|
return sessionService.createSession({ checks: { user: { loginName } } }, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setSession(
|
||||||
|
server: ZitadelServer,
|
||||||
|
loginName: string
|
||||||
|
): Promise<any | undefined> {
|
||||||
|
const sessionService = session.getSession(server);
|
||||||
|
return sessionService.setSession({ checks: { user: { loginName } } }, {});
|
||||||
|
}
|
||||||
|
|
||||||
export type AddHumanUserData = {
|
export type AddHumanUserData = {
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
|||||||
84
apps/login/ui/PasswordForm.tsx
Normal file
84
apps/login/ui/PasswordForm.tsx
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Button, ButtonVariants } from "./Button";
|
||||||
|
import { TextInput } from "./Input";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { Spinner } from "./Spinner";
|
||||||
|
|
||||||
|
type Inputs = {
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function UsernameForm() {
|
||||||
|
const { register, handleSubmit, formState } = useForm<Inputs>({
|
||||||
|
mode: "onBlur",
|
||||||
|
});
|
||||||
|
|
||||||
|
const [error, setError] = useState<string>("");
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
async function submitUsername(values: Inputs) {
|
||||||
|
setLoading(true);
|
||||||
|
const res = await fetch("/session", {
|
||||||
|
method: "PUT",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
password: values.password,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
setLoading(false);
|
||||||
|
throw new Error("Failed to register user");
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitAndLink(value: Inputs): Promise<boolean | void> {
|
||||||
|
return submitUsername(value).then((resp: any) => {
|
||||||
|
return router.push(`/password`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { errors } = formState;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form className="w-full">
|
||||||
|
<div className="">
|
||||||
|
<TextInput
|
||||||
|
type="password"
|
||||||
|
autoComplete="password"
|
||||||
|
{...register("password", { required: "This field is required" })}
|
||||||
|
label="Loginname"
|
||||||
|
// error={errors.username?.message as string}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8 flex w-full flex-row items-center">
|
||||||
|
{/* <Button type="button" variant={ButtonVariants.Secondary}>
|
||||||
|
back
|
||||||
|
</Button> */}
|
||||||
|
<span className="flex-grow"></span>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
className="self-end"
|
||||||
|
variant={ButtonVariants.Primary}
|
||||||
|
disabled={loading || !formState.isValid}
|
||||||
|
onClick={handleSubmit(submitAndLink)}
|
||||||
|
>
|
||||||
|
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
||||||
|
continue
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { PasswordComplexityPolicy, PrivacyPolicy } from "@zitadel/server";
|
import {
|
||||||
|
LegalAndSupportSettings,
|
||||||
|
PasswordComplexitySettings,
|
||||||
|
} from "@zitadel/server";
|
||||||
import PasswordComplexity from "./PasswordComplexity";
|
import PasswordComplexity from "./PasswordComplexity";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Button, ButtonVariants } from "./Button";
|
import { Button, ButtonVariants } from "./Button";
|
||||||
@@ -27,8 +30,8 @@ type Inputs =
|
|||||||
| FieldValues;
|
| FieldValues;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
privacyPolicy: PrivacyPolicy;
|
privacyPolicy: LegalAndSupportSettings;
|
||||||
passwordComplexityPolicy: PasswordComplexityPolicy;
|
passwordComplexityPolicy: PasswordComplexitySettings;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RegisterForm({
|
export default function RegisterForm({
|
||||||
@@ -90,10 +93,10 @@ export default function RegisterForm({
|
|||||||
|
|
||||||
const policyIsValid =
|
const policyIsValid =
|
||||||
passwordComplexityPolicy &&
|
passwordComplexityPolicy &&
|
||||||
(passwordComplexityPolicy.hasLowercase ? hasLowercase : true) &&
|
(passwordComplexityPolicy.requiresLowercase ? hasLowercase : true) &&
|
||||||
(passwordComplexityPolicy.hasNumber ? hasNumber : true) &&
|
(passwordComplexityPolicy.requiresNumber ? hasNumber : true) &&
|
||||||
(passwordComplexityPolicy.hasUppercase ? hasUppercase : true) &&
|
(passwordComplexityPolicy.requiresUppercase ? hasUppercase : true) &&
|
||||||
(passwordComplexityPolicy.hasSymbol ? hasSymbol : true) &&
|
(passwordComplexityPolicy.requiresSymbol ? hasSymbol : true) &&
|
||||||
hasMinLength;
|
hasMinLength;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { setTheme, LabelPolicyColors } from "#/utils/colors";
|
import { BrandingSettings } from "@zitadel/server";
|
||||||
|
import { setTheme } from "#/utils/colors";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
branding: LabelPolicyColors | undefined;
|
branding: Partial<BrandingSettings> | undefined;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
82
apps/login/ui/UsernameForm.tsx
Normal file
82
apps/login/ui/UsernameForm.tsx
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Button, ButtonVariants } from "./Button";
|
||||||
|
import { TextInput } from "./Input";
|
||||||
|
import { useForm } from "react-hook-form";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { Spinner } from "./Spinner";
|
||||||
|
|
||||||
|
type Inputs = {
|
||||||
|
loginName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function UsernameForm() {
|
||||||
|
const { register, handleSubmit, formState } = useForm<Inputs>({
|
||||||
|
mode: "onBlur",
|
||||||
|
});
|
||||||
|
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
async function submitUsername(values: Inputs) {
|
||||||
|
setLoading(true);
|
||||||
|
const res = await fetch("/session", {
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
loginName: values.loginName,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
setLoading(false);
|
||||||
|
throw new Error("Failed to register user");
|
||||||
|
}
|
||||||
|
|
||||||
|
setLoading(false);
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
function submitAndLink(value: Inputs): Promise<boolean | void> {
|
||||||
|
return submitUsername(value).then((resp: any) => {
|
||||||
|
return router.push(`/password`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const { errors } = formState;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<form className="w-full">
|
||||||
|
<div className="">
|
||||||
|
<TextInput
|
||||||
|
type="text"
|
||||||
|
autoComplete="username"
|
||||||
|
{...register("loginName", { required: "This field is required" })}
|
||||||
|
label="Loginname"
|
||||||
|
// error={errors.username?.message as string}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8 flex w-full flex-row items-center">
|
||||||
|
{/* <Button type="button" variant={ButtonVariants.Secondary}>
|
||||||
|
back
|
||||||
|
</Button> */}
|
||||||
|
<span className="flex-grow"></span>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
className="self-end"
|
||||||
|
variant={ButtonVariants.Primary}
|
||||||
|
disabled={loading || !formState.isValid}
|
||||||
|
onClick={handleSubmit(submitAndLink)}
|
||||||
|
>
|
||||||
|
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
||||||
|
continue
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import tinycolor from "tinycolor2";
|
import tinycolor from "tinycolor2";
|
||||||
|
|
||||||
|
import { BrandingSettings } from "@zitadel/server";
|
||||||
|
|
||||||
export interface Color {
|
export interface Color {
|
||||||
name: string;
|
name: string;
|
||||||
hex: string;
|
hex: string;
|
||||||
@@ -52,32 +54,36 @@ export type LabelPolicyColors = {
|
|||||||
primaryColorDark: string;
|
primaryColorDark: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function setTheme(document: any, policy?: LabelPolicyColors) {
|
type BrandingColors = {
|
||||||
const lP = {
|
lightTheme: {
|
||||||
backgroundColor: BACKGROUND,
|
backgroundColor: string;
|
||||||
backgroundColorDark: DARK_BACKGROUND,
|
fontColor: string;
|
||||||
primaryColor: PRIMARY,
|
primaryColor: string;
|
||||||
primaryColorDark: DARK_PRIMARY,
|
warnColor: string;
|
||||||
warnColor: WARN,
|
|
||||||
warnColorDark: DARK_WARN,
|
|
||||||
fontColor: TEXT,
|
|
||||||
fontColorDark: DARK_TEXT,
|
|
||||||
linkColor: TEXT,
|
|
||||||
linkColorDark: DARK_TEXT,
|
|
||||||
};
|
};
|
||||||
|
darkTheme: {
|
||||||
|
backgroundColor: string;
|
||||||
|
fontColor: string;
|
||||||
|
primaryColor: string;
|
||||||
|
warnColor: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
if (policy) {
|
export function setTheme(document: any, policy?: Partial<BrandingSettings>) {
|
||||||
lP.backgroundColor = policy.backgroundColor;
|
const lP: BrandingColors = {
|
||||||
lP.backgroundColorDark = policy.backgroundColorDark;
|
lightTheme: {
|
||||||
lP.primaryColor = policy.primaryColor;
|
backgroundColor: policy?.lightTheme?.backgroundColor ?? BACKGROUND,
|
||||||
lP.primaryColorDark = policy.primaryColorDark;
|
fontColor: policy?.lightTheme?.fontColor ?? TEXT,
|
||||||
lP.warnColor = policy.warnColor;
|
primaryColor: policy?.lightTheme?.primaryColor ?? PRIMARY,
|
||||||
lP.warnColorDark = policy.warnColorDark;
|
warnColor: policy?.lightTheme?.warnColor ?? WARN,
|
||||||
lP.fontColor = policy.fontColor;
|
},
|
||||||
lP.fontColorDark = policy.fontColorDark;
|
darkTheme: {
|
||||||
lP.linkColor = policy.fontColor;
|
backgroundColor: policy?.darkTheme?.backgroundColor ?? DARK_BACKGROUND,
|
||||||
lP.linkColorDark = policy.fontColorDark;
|
fontColor: policy?.darkTheme?.fontColor ?? DARK_TEXT,
|
||||||
}
|
primaryColor: policy?.darkTheme?.primaryColor ?? DARK_PRIMARY,
|
||||||
|
warnColor: policy?.darkTheme?.warnColor ?? DARK_WARN,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
const dark = computeMap(lP, true);
|
const dark = computeMap(lP, true);
|
||||||
const light = computeMap(lP, false);
|
const light = computeMap(lP, false);
|
||||||
@@ -177,25 +183,24 @@ function getContrast(color: string): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function computeMap(
|
export function computeMap(branding: BrandingColors, dark: boolean): ColorMap {
|
||||||
labelpolicy: LabelPolicyColors,
|
|
||||||
dark: boolean
|
|
||||||
): ColorMap {
|
|
||||||
return {
|
return {
|
||||||
background: computeColors(
|
background: computeColors(
|
||||||
dark ? labelpolicy.backgroundColorDark : labelpolicy.backgroundColor
|
dark
|
||||||
|
? branding.darkTheme.backgroundColor
|
||||||
|
: branding.lightTheme.backgroundColor
|
||||||
),
|
),
|
||||||
primary: computeColors(
|
primary: computeColors(
|
||||||
dark ? labelpolicy.primaryColorDark : labelpolicy.primaryColor
|
dark ? branding.darkTheme.primaryColor : branding.lightTheme.primaryColor
|
||||||
),
|
),
|
||||||
warn: computeColors(
|
warn: computeColors(
|
||||||
dark ? labelpolicy.warnColorDark : labelpolicy.warnColor
|
dark ? branding.darkTheme.warnColor : branding.lightTheme.warnColor
|
||||||
),
|
),
|
||||||
text: computeColors(
|
text: computeColors(
|
||||||
dark ? labelpolicy.fontColorDark : labelpolicy.fontColor
|
dark ? branding.darkTheme.fontColor : branding.lightTheme.fontColor
|
||||||
),
|
),
|
||||||
link: computeColors(
|
link: computeColors(
|
||||||
dark ? labelpolicy.fontColorDark : labelpolicy.fontColor
|
dark ? branding.darkTheme.fontColor : branding.lightTheme.fontColor
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,14 +4,15 @@
|
|||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"module": "./dist/index.mjs",
|
"module": "./dist/index.mjs",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
|
"type": "commonjs",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"files": [
|
"files": [
|
||||||
"dist/**"
|
"dist/**"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsup src/index.ts src/*/index.ts --format esm,cjs --dts",
|
"build": "tsup --dts",
|
||||||
"dev": "tsup src/index.ts src/*/index.ts --format esm,cjs --watch --dts",
|
"dev": "tsup --dts --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",
|
||||||
"prebuild": "pnpm run generate",
|
"prebuild": "pnpm run generate",
|
||||||
|
|||||||
@@ -1,13 +1,36 @@
|
|||||||
export * from "./server";
|
import * as management from "./management";
|
||||||
|
import * as settings from "./v2/settings";
|
||||||
|
import * as session from "./v2/session";
|
||||||
|
|
||||||
|
import * as login from "./proto/server/zitadel/settings/v2alpha/login_settings";
|
||||||
|
import * as password from "./proto/server/zitadel/settings/v2alpha/password_settings";
|
||||||
|
import * as legal from "./proto/server/zitadel/settings/v2alpha/legal_settings";
|
||||||
|
|
||||||
|
export {
|
||||||
|
BrandingSettings,
|
||||||
|
Theme,
|
||||||
|
} from "./proto/server/zitadel/settings/v2alpha/branding_settings";
|
||||||
|
|
||||||
|
export { type LegalAndSupportSettings } from "./proto/server/zitadel/settings/v2alpha/legal_settings";
|
||||||
|
export { type PasswordComplexitySettings } from "./proto/server/zitadel/settings/v2alpha/password_settings";
|
||||||
|
|
||||||
|
import {
|
||||||
|
getServers,
|
||||||
|
initializeServer,
|
||||||
|
ZitadelServer,
|
||||||
|
ZitadelServerOptions,
|
||||||
|
} from "./server";
|
||||||
export * from "./middleware";
|
export * from "./middleware";
|
||||||
export * as management from "./management";
|
|
||||||
export * as settings from "./v2/settings";
|
|
||||||
|
|
||||||
// export * as auth from "./auth";
|
export {
|
||||||
// export * as management from "./management";
|
getServers,
|
||||||
// export * as admin from "./admin";
|
ZitadelServer,
|
||||||
// export * as system from "./system";
|
type ZitadelServerOptions,
|
||||||
|
initializeServer,
|
||||||
// export * from "./proto/server/zitadel/management";
|
management,
|
||||||
// export * from "./proto/server/zitadel/system";
|
session,
|
||||||
// export * from "./proto/server/zitadel/admin";
|
settings,
|
||||||
|
login,
|
||||||
|
password,
|
||||||
|
legal,
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
export * from "./management";
|
export * from "./management";
|
||||||
export * as management from "../proto/server/zitadel/management";
|
export * as management from "../proto/server/zitadel/management";
|
||||||
export * from "../proto/server/zitadel/policy";
|
export * as policy from "../proto/server/zitadel/policy";
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
import { createChannel, createClientFactory } from "nice-grpc";
|
||||||
|
import {
|
||||||
|
SettingsServiceClient,
|
||||||
|
SettingsServiceDefinition,
|
||||||
|
} from "./proto/server/zitadel/settings/v2alpha/settings_service";
|
||||||
|
import { authMiddleware } from "./middleware";
|
||||||
|
import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions";
|
||||||
|
|
||||||
let apps: ZitadelServer[] = [];
|
let apps: ZitadelServer[] = [];
|
||||||
|
|
||||||
export interface ZitadelServerProps {
|
export interface ZitadelServerProps {
|
||||||
@@ -49,3 +57,18 @@ export function getServer(name?: string): ZitadelServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const createClient = <Client>(
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|||||||
2
packages/zitadel-server/src/v2/session/index.ts
Normal file
2
packages/zitadel-server/src/v2/session/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from "./session";
|
||||||
|
export * from "../../proto/server/zitadel/session/v2alpha/session";
|
||||||
29
packages/zitadel-server/src/v2/session/session.ts
Normal file
29
packages/zitadel-server/src/v2/session/session.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions";
|
||||||
|
|
||||||
|
import {
|
||||||
|
SessionServiceClient,
|
||||||
|
SessionServiceDefinition,
|
||||||
|
} from "../../proto/server/zitadel/session/v2alpha/session_service";
|
||||||
|
|
||||||
|
import { ZitadelServer, createClient, getServers } from "../../server";
|
||||||
|
|
||||||
|
export const getSession = (server?: string | ZitadelServer) => {
|
||||||
|
console.log("init session");
|
||||||
|
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<SessionServiceClient>(
|
||||||
|
SessionServiceDefinition as CompatServiceDefinition,
|
||||||
|
config.apiUrl,
|
||||||
|
config.token
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -1,6 +1,2 @@
|
|||||||
export * from "./settings";
|
export * from "./settings";
|
||||||
export * from "../../proto/server/zitadel/settings/v2alpha/settings";
|
export * from "../../proto/server/zitadel/settings/v2alpha/settings";
|
||||||
export * as branding from "../../proto/server/zitadel/settings/v2alpha/branding_settings";
|
|
||||||
export * as login from "../../proto/server/zitadel/settings/v2alpha/login_settings";
|
|
||||||
export * as password from "../../proto/server/zitadel/settings/v2alpha/password_settings";
|
|
||||||
export * as legal from "../../proto/server/zitadel/settings/v2alpha/legal_settings";
|
|
||||||
|
|||||||
@@ -1,28 +1,11 @@
|
|||||||
import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions";
|
import { CompatServiceDefinition } from "nice-grpc/lib/service-definitions";
|
||||||
|
|
||||||
import { createChannel, createClientFactory } from "nice-grpc";
|
|
||||||
import {
|
import {
|
||||||
SettingsServiceClient,
|
SettingsServiceClient,
|
||||||
SettingsServiceDefinition,
|
SettingsServiceDefinition,
|
||||||
} from "../../proto/server/zitadel/settings/v2alpha/settings_service";
|
} from "../../proto/server/zitadel/settings/v2alpha/settings_service";
|
||||||
|
|
||||||
import { authMiddleware } from "../../middleware";
|
import { ZitadelServer, createClient, getServers } from "../../server";
|
||||||
import { ZitadelServer, getServers } from "../../server";
|
|
||||||
|
|
||||||
const createClient = <Client>(
|
|
||||||
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 getSettings = (server?: string | ZitadelServer) => {
|
export const getSettings = (server?: string | ZitadelServer) => {
|
||||||
console.log("init settings");
|
console.log("init settings");
|
||||||
|
|||||||
@@ -3,12 +3,7 @@
|
|||||||
"include": ["src/**/*.ts"],
|
"include": ["src/**/*.ts"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"rootDir": "src",
|
"rootDir": "src"
|
||||||
"paths": {
|
|
||||||
"#": ["."],
|
|
||||||
"*": ["./*"],
|
|
||||||
"#/*": ["./*"]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"exclude": ["dist", "build", "node_modules"]
|
"exclude": ["dist", "build", "node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
13
packages/zitadel-server/tsup.config.ts
Normal file
13
packages/zitadel-server/tsup.config.ts
Normal 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,
|
||||||
|
}));
|
||||||
Reference in New Issue
Block a user