fix build

This commit is contained in:
Elio Bischof
2025-07-18 01:10:35 +02:00
parent e61997b7e9
commit 98c53c0321
19 changed files with 316 additions and 43 deletions

View File

@@ -1,7 +1,7 @@
import { clsx } from "clsx"; import { clsx } from "clsx";
import { ButtonHTMLAttributes, DetailedHTMLProps, forwardRef } from "react"; import { ButtonHTMLAttributes, DetailedHTMLProps, forwardRef } from "react";
enum ButtonSizes { export enum ButtonSizes {
Small = "Small", Small = "Small",
Large = "Large", Large = "Large",
} }
@@ -9,15 +9,16 @@ enum ButtonSizes {
export enum ButtonVariants { export enum ButtonVariants {
Primary = "Primary", Primary = "Primary",
Secondary = "Secondary", Secondary = "Secondary",
Destructive = "Destructive",
} }
enum ButtonColors { export enum ButtonColors {
Neutral = "Neutral", Neutral = "Neutral",
Primary = "Primary", Primary = "Primary",
Warn = "Warn", Warn = "Warn",
} }
type ButtonProps = DetailedHTMLProps< export type ButtonProps = DetailedHTMLProps<
ButtonHTMLAttributes<HTMLButtonElement>, ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement HTMLButtonElement
> & { > & {
@@ -26,7 +27,7 @@ type ButtonProps = DetailedHTMLProps<
color?: ButtonColors; color?: ButtonColors;
}; };
const getButtonClasses = ( export const getButtonClasses = (
size: ButtonSizes, size: ButtonSizes,
variant: ButtonVariants, variant: ButtonVariants,
color: ButtonColors, color: ButtonColors,

View File

@@ -7,7 +7,7 @@ import {
useState, useState,
} from "react"; } from "react";
type CheckboxProps = DetailedHTMLProps< export type CheckboxProps = DetailedHTMLProps<
InputHTMLAttributes<HTMLInputElement>, InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement HTMLInputElement
> & { > & {

View File

@@ -10,7 +10,7 @@ import {
ReactNode, ReactNode,
} from "react"; } from "react";
type TextInputProps = DetailedHTMLProps< export type TextInputProps = DetailedHTMLProps<
InputHTMLAttributes<HTMLInputElement>, InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement HTMLInputElement
> & { > & {

View File

@@ -17,7 +17,7 @@ import { SignInWithGitlab } from "./idps/sign-in-with-gitlab";
import { SignInWithGoogle } from "./idps/sign-in-with-google"; import { SignInWithGoogle } from "./idps/sign-in-with-google";
import { Translated } from "./translated"; import { Translated } from "./translated";
interface SignInWithIDPProps { export interface SignInWithIDPProps {
children?: ReactNode; children?: ReactNode;
identityProviders: IdentityProvider[]; identityProviders: IdentityProvider[];
requestId?: string; requestId?: string;

View File

@@ -8,7 +8,7 @@ export enum BadgeState {
Alert = "alert", Alert = "alert",
} }
type StateBadgeProps = { export type StateBadgeProps = {
state: BadgeState; state: BadgeState;
children: ReactNode; children: ReactNode;
evenPadding?: boolean; evenPadding?: boolean;

View File

@@ -1,30 +1,57 @@
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb"; import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
import tinycolor from "tinycolor2"; import tinycolor from "tinycolor2";
interface Color { export interface Color {
name: string; name: string;
hex: string; hex: string;
rgb: string; rgb: string;
contrastColor: string; contrastColor: string;
} }
type MapName = "background" | "primary" | "warn" | "text" | "link"; export type MapName = "background" | "primary" | "warn" | "text" | "link";
type ColorMap = { export type ColorName =
[_key in MapName]: Color[]; | "50"
| "100"
| "200"
| "300"
| "400"
| "500"
| "600"
| "700"
| "800"
| "C900"
| "A100"
| "A200"
| "A400"
| "A700";
export type ColorMap = {
[key in MapName]: Color[];
}; };
const DARK_PRIMARY = "#2073c4"; export const DARK_PRIMARY = "#2073c4";
const PRIMARY = "#5469d4"; export const PRIMARY = "#5469d4";
const DARK_WARN = "#ff3b5b"; export const DARK_WARN = "#ff3b5b";
const WARN = "#cd3d56"; export const WARN = "#cd3d56";
const DARK_BACKGROUND = "#111827"; export const DARK_BACKGROUND = "#111827";
const BACKGROUND = "#fafafa"; export const BACKGROUND = "#fafafa";
const DARK_TEXT = "#ffffff"; export const DARK_TEXT = "#ffffff";
const TEXT = "#000000"; export const TEXT = "#000000";
export type LabelPolicyColors = {
backgroundColor: string;
backgroundColorDark: string;
fontColor: string;
fontColorDark: string;
warnColor: string;
warnColorDark: string;
primaryColor: string;
primaryColorDark: string;
};
type BrandingColors = { type BrandingColors = {
lightTheme: { lightTheme: {
@@ -155,7 +182,7 @@ function getContrast(color: string): string {
} }
} }
function computeMap(branding: BrandingColors, dark: boolean): ColorMap { export function computeMap(branding: BrandingColors, dark: boolean): ColorMap {
return { return {
background: computeColors( background: computeColors(
dark dark
@@ -186,7 +213,7 @@ export interface ColorShade {
900: string; 900: string;
} }
const COLORS = [ export const COLORS = [
{ {
500: "#ef4444", 500: "#ef4444",
200: "#fecaca", 200: "#fecaca",
@@ -336,7 +363,7 @@ export function getColorHash(value: string): ColorShade {
return COLORS[hash % COLORS.length]; return COLORS[hash % COLORS.length];
} }
function hashCode(str: string, seed = 0): number { export function hashCode(str: string, seed = 0): number {
let h1 = 0xdeadbeef ^ seed, let h1 = 0xdeadbeef ^ seed,
h2 = 0x41c6ce57 ^ seed; h2 = 0x41c6ce57 ^ seed;
for (let i = 0, ch; i < str.length; i++) { for (let i = 0, ch; i < str.length; i++) {
@@ -352,3 +379,61 @@ function hashCode(str: string, seed = 0): number {
Math.imul(h1 ^ (h1 >>> 13), 3266489909); Math.imul(h1 ^ (h1 >>> 13), 3266489909);
return 4294967296 * (2097151 & h2) + (h1 >>> 0); return 4294967296 * (2097151 & h2) + (h1 >>> 0);
} }
export function getMembershipColor(role: string): ColorShade {
const hash = hashCode(role);
let color = COLORS[hash % COLORS.length];
switch (role) {
case "IAM_OWNER":
color = COLORS[0];
break;
case "IAM_OWNER_VIEWER":
color = COLORS[14];
break;
case "IAM_ORG_MANAGER":
color = COLORS[11];
break;
case "IAM_USER_MANAGER":
color = COLORS[8];
break;
case "ORG_OWNER":
color = COLORS[16];
break;
case "ORG_USER_MANAGER":
color = COLORS[8];
break;
case "ORG_OWNER_VIEWER":
color = COLORS[14];
break;
case "ORG_USER_PERMISSION_EDITOR":
color = COLORS[7];
break;
case "ORG_PROJECT_PERMISSION_EDITOR":
color = COLORS[11];
break;
case "ORG_PROJECT_CREATOR":
color = COLORS[12];
break;
case "PROJECT_OWNER":
color = COLORS[9];
break;
case "PROJECT_OWNER_VIEWER":
color = COLORS[10];
break;
case "PROJECT_OWNER_GLOBAL":
color = COLORS[11];
break;
case "PROJECT_OWNER_VIEWER_GLOBAL":
color = COLORS[12];
break;
default:
color = COLORS[hash % COLORS.length];
break;
}
return color;
}

View File

@@ -7,11 +7,11 @@ import { cookies, headers } from "next/headers";
import { userAgent } from "next/server"; import { userAgent } from "next/server";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
async function getFingerprintId() { export async function getFingerprintId() {
return uuidv4(); return uuidv4();
} }
async function setFingerprintIdCookie(fingerprintId: string) { export async function setFingerprintIdCookie(fingerprintId: string) {
const cookiesList = await cookies(); const cookiesList = await cookies();
return cookiesList.set({ return cookiesList.set({

View File

@@ -35,3 +35,4 @@ export const LANGS: Lang[] = [
]; ];
export const LANGUAGE_COOKIE_NAME = "NEXT_LOCALE"; export const LANGUAGE_COOKIE_NAME = "NEXT_LOCALE";
export const LANGUAGE_HEADER_NAME = "accept-language";

View File

@@ -19,7 +19,7 @@ type LoginWithSAMLAndSession = {
request: NextRequest; request: NextRequest;
}; };
async function getSAMLFormUID() { export async function getSAMLFormUID() {
return uuidv4(); return uuidv4();
} }

View File

@@ -15,6 +15,7 @@ import {
ErrorDetail, ErrorDetail,
} from "@zitadel/proto/zitadel/message_pb"; } from "@zitadel/proto/zitadel/message_pb";
import { import {
Challenges,
RequestChallenges, RequestChallenges,
} from "@zitadel/proto/zitadel/session/v2/challenge_pb"; } from "@zitadel/proto/zitadel/session/v2/challenge_pb";
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb"; import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
@@ -185,6 +186,10 @@ export async function createSessionForIdpAndUpdateCookie({
}); });
} }
export type SessionWithChallenges = Session & {
challenges: Challenges | undefined;
};
export async function setSessionAndUpdateCookie( export async function setSessionAndUpdateCookie(
recentCookie: CustomCookieData, recentCookie: CustomCookieData,
checks?: Checks, checks?: Checks,

View File

@@ -13,7 +13,7 @@ import { getServiceUrlFromHeaders } from "../service-url";
import { checkEmailVerification } from "../verify-helper"; import { checkEmailVerification } from "../verify-helper";
import { createSessionForIdpAndUpdateCookie } from "./cookie"; import { createSessionForIdpAndUpdateCookie } from "./cookie";
type RedirectToIdpState = { error?: string | null } | undefined; export type RedirectToIdpState = { error?: string | null } | undefined;
export async function redirectToIdp( export async function redirectToIdp(
prevState: RedirectToIdpState, prevState: RedirectToIdpState,
@@ -63,7 +63,7 @@ export async function redirectToIdp(
return { error: "Unexpected response from IDP flow" }; return { error: "Unexpected response from IDP flow" };
} }
type StartIDPFlowCommand = { export type StartIDPFlowCommand = {
serviceUrl: string; serviceUrl: string;
host: string; host: string;
idpId: string; idpId: string;

View File

@@ -81,7 +81,7 @@ export async function resetPassword(command: ResetPasswordCommand) {
}); });
} }
type UpdateSessionCommand = { export type UpdateSessionCommand = {
loginName: string; loginName: string;
organization?: string; organization?: string;
checks: Checks; checks: Checks;

View File

@@ -11,6 +11,7 @@ import {
getUserByID, getUserByID,
} from "@/lib/zitadel"; } from "@/lib/zitadel";
import { create } from "@zitadel/client"; import { create } from "@zitadel/client";
import { Factors } from "@zitadel/proto/zitadel/session/v2/session_pb";
import { import {
ChecksJson, ChecksJson,
ChecksSchema, ChecksSchema,
@@ -29,6 +30,11 @@ type RegisterUserCommand = {
requestId?: string; requestId?: string;
}; };
export type RegisterUserResponse = {
userId: string;
sessionId: string;
factors: Factors | undefined;
};
export async function registerUser(command: RegisterUserCommand) { export async function registerUser(command: RegisterUserCommand) {
const _headers = await headers(); const _headers = await headers();
const { serviceUrl } = getServiceUrlFromHeaders(_headers); const { serviceUrl } = getServiceUrlFromHeaders(_headers);
@@ -151,6 +157,11 @@ type RegisterUserAndLinkToIDPommand = {
idpUserName: string; idpUserName: string;
}; };
export type registerUserAndLinkToIDPResponse = {
userId: string;
sessionId: string;
factors: Factors | undefined;
};
export async function registerUserAndLinkToIDP( export async function registerUserAndLinkToIDP(
command: RegisterUserAndLinkToIDPommand, command: RegisterUserAndLinkToIDPommand,
) { ) {

View File

@@ -105,7 +105,7 @@ export async function continueWithSession({
} }
} }
type UpdateSessionCommand = { export type UpdateSessionCommand = {
loginName?: string; loginName?: string;
sessionId?: string; sessionId?: string;
organization?: string; organization?: string;

View File

@@ -47,6 +47,34 @@ export function checkPasswordChangeRequired(
} }
} }
export function checkEmailVerified(
session: Session,
humanUser?: HumanUser,
organization?: string,
requestId?: string,
) {
if (!humanUser?.email?.isVerified) {
const paramsVerify = new URLSearchParams({
loginName: session.factors?.user?.loginName as string,
userId: session.factors?.user?.id as string, // verify needs user id
send: "true", // we request a new email code once the page is loaded
});
if (organization || session.factors?.user?.organizationId) {
paramsVerify.append(
"organization",
organization ?? (session.factors?.user?.organizationId as string),
);
}
if (requestId) {
paramsVerify.append("requestId", requestId);
}
return { redirect: "/verify?" + paramsVerify };
}
}
export function checkEmailVerification( export function checkEmailVerification(
session: Session, session: Session,
humanUser?: HumanUser, humanUser?: HumanUser,

View File

@@ -40,6 +40,8 @@ import { SendInviteCodeSchema } from "@zitadel/proto/zitadel/user/v2/user_pb";
import { import {
AddHumanUserRequest, AddHumanUserRequest,
AddHumanUserRequestSchema, AddHumanUserRequestSchema,
ResendEmailCodeRequest,
ResendEmailCodeRequestSchema,
SendEmailCodeRequestSchema, SendEmailCodeRequestSchema,
SetPasswordRequest, SetPasswordRequest,
SetPasswordRequestSchema, SetPasswordRequestSchema,
@@ -62,6 +64,41 @@ async function cacheWrapper<T>(callback: Promise<T>) {
return callback; return callback;
} }
export async function getHostedLoginTranslation({
serviceUrl,
organization,
locale,
}: {
serviceUrl: string;
organization?: string;
locale?: string;
}) {
const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, serviceUrl);
const callback = settingsService
.getHostedLoginTranslation(
{
level: organization
? {
case: "organizationId",
value: organization,
}
: {
case: "instance",
value: true,
},
locale: locale,
},
{},
)
.then((resp) => {
return resp.translations ? resp.translations : undefined;
});
return useCache ? cacheWrapper(callback) : callback;
}
export async function getBrandingSettings({ export async function getBrandingSettings({
serviceUrl, serviceUrl,
organization, organization,
@@ -205,6 +242,21 @@ export async function registerTOTP({
return userService.registerTOTP({ userId }, {}); return userService.registerTOTP({ userId }, {});
} }
export async function getGeneralSettings({
serviceUrl,
}: {
serviceUrl: string;
}) {
const settingsService: Client<typeof SettingsService> =
await createServiceForHost(SettingsService, serviceUrl);
const callback = settingsService
.getGeneralSettings({}, {})
.then((resp) => resp.supportedLanguages);
return useCache ? cacheWrapper(callback) : callback;
}
export async function getLegalAndSupportSettings({ export async function getLegalAndSupportSettings({
serviceUrl, serviceUrl,
organization, organization,
@@ -375,7 +427,7 @@ export async function listSessions({ serviceUrl, ids }: ListSessionsCommand) {
); );
} }
type AddHumanUserData = { export type AddHumanUserData = {
serviceUrl: string; serviceUrl: string;
firstName: string; firstName: string;
lastName: string; lastName: string;
@@ -587,7 +639,7 @@ export async function createInviteCode({
); );
} }
type ListUsersCommand = { export type ListUsersCommand = {
serviceUrl: string; serviceUrl: string;
loginName?: string; loginName?: string;
userName?: string; userName?: string;
@@ -1151,6 +1203,33 @@ export async function verifyEmail({
); );
} }
export async function resendEmailCode({
serviceUrl,
userId,
urlTemplate,
}: {
serviceUrl: string;
userId: string;
urlTemplate: string;
}) {
let request: ResendEmailCodeRequest = create(ResendEmailCodeRequestSchema, {
userId,
});
const medium = create(SendEmailVerificationCodeSchema, {
urlTemplate,
});
request = { ...request, verification: { case: "sendCode", value: medium } };
const userService: Client<typeof UserService> = await createServiceForHost(
UserService,
serviceUrl,
);
return userService.resendEmailCode(request, {});
}
export async function retrieveIDPIntent({ export async function retrieveIDPIntent({
serviceUrl, serviceUrl,
id, id,

View File

@@ -17,6 +17,7 @@
} }
}, },
"devDependencies": { "devDependencies": {
"@changesets/cli": "^2.29.5" "@changesets/cli": "^2.29.5",
"turbo": "2.5.5"
} }
} }

64
pnpm-lock.yaml generated
View File

@@ -16,6 +16,9 @@ importers:
'@changesets/cli': '@changesets/cli':
specifier: ^2.29.5 specifier: ^2.29.5
version: 2.29.5 version: 2.29.5
turbo:
specifier: 2.5.5
version: 2.5.5
apps/login: apps/login:
dependencies: dependencies:
@@ -13036,6 +13039,40 @@ packages:
tunnel-agent@0.6.0: tunnel-agent@0.6.0:
resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==}
turbo-darwin-64@2.5.5:
resolution: {integrity: sha512-RYnTz49u4F5tDD2SUwwtlynABNBAfbyT2uU/brJcyh5k6lDLyNfYKdKmqd3K2ls4AaiALWrFKVSBsiVwhdFNzQ==}
cpu: [x64]
os: [darwin]
turbo-darwin-arm64@2.5.5:
resolution: {integrity: sha512-Tk+ZeSNdBobZiMw9aFypQt0DlLsWSFWu1ymqsAdJLuPoAH05qCfYtRxE1pJuYHcJB5pqI+/HOxtJoQ40726Btw==}
cpu: [arm64]
os: [darwin]
turbo-linux-64@2.5.5:
resolution: {integrity: sha512-2/XvMGykD7VgsvWesZZYIIVXMlgBcQy+ZAryjugoTcvJv8TZzSU/B1nShcA7IAjZ0q7OsZ45uP2cOb8EgKT30w==}
cpu: [x64]
os: [linux]
turbo-linux-arm64@2.5.5:
resolution: {integrity: sha512-DW+8CjCjybu0d7TFm9dovTTVg1VRnlkZ1rceO4zqsaLrit3DgHnN4to4uwyuf9s2V/BwS3IYcRy+HG9BL596Iw==}
cpu: [arm64]
os: [linux]
turbo-windows-64@2.5.5:
resolution: {integrity: sha512-q5p1BOy8ChtSZfULuF1BhFMYIx6bevXu4fJ+TE/hyNfyHJIfjl90Z6jWdqAlyaFLmn99X/uw+7d6T/Y/dr5JwQ==}
cpu: [x64]
os: [win32]
turbo-windows-arm64@2.5.5:
resolution: {integrity: sha512-AXbF1KmpHUq3PKQwddMGoKMYhHsy5t1YBQO8HZ04HLMR0rWv9adYlQ8kaeQJTko1Ay1anOBFTqaxfVOOsu7+1Q==}
cpu: [arm64]
os: [win32]
turbo@2.5.5:
resolution: {integrity: sha512-eZ7wI6KjtT1eBqCnh2JPXWNUAxtoxxfi6VdBdZFvil0ychCOTxbm7YLRBi1JSt7U3c+u3CLxpoPxLdvr/Npr3A==}
hasBin: true
tweetnacl@0.14.5: tweetnacl@0.14.5:
resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==}
@@ -30716,6 +30753,33 @@ snapshots:
dependencies: dependencies:
safe-buffer: 5.2.1 safe-buffer: 5.2.1
turbo-darwin-64@2.5.5:
optional: true
turbo-darwin-arm64@2.5.5:
optional: true
turbo-linux-64@2.5.5:
optional: true
turbo-linux-arm64@2.5.5:
optional: true
turbo-windows-64@2.5.5:
optional: true
turbo-windows-arm64@2.5.5:
optional: true
turbo@2.5.5:
optionalDependencies:
turbo-darwin-64: 2.5.5
turbo-darwin-arm64: 2.5.5
turbo-linux-64: 2.5.5
turbo-linux-arm64: 2.5.5
turbo-windows-64: 2.5.5
turbo-windows-arm64: 2.5.5
tweetnacl@0.14.5: {} tweetnacl@0.14.5: {}
type-check@0.4.0: type-check@0.4.0:

View File

@@ -21,16 +21,14 @@
"cache": true "cache": true
}, },
"build": {}, "build": {},
"build:login:standalone": {}, "quality": {
"build:client:standalone": {}, "with": [
"test": {}, "lint",
"start": {}, "test:unit"
"start:built": {}, ]
"test:unit": {},
"test:unit:standalone": {},
"test:watch": {
"persistent": true
}, },
"start": {},
"test:unit": {},
"lint": {}, "lint": {},
"lint:fix": {}, "lint:fix": {},
"dev": { "dev": {