mirror of
https://github.com/zitadel/zitadel.git
synced 2025-08-11 20:17:32 +00:00
Merge branch 'main' into saml-post
This commit is contained in:
@@ -22,7 +22,8 @@
|
|||||||
"loginname": {
|
"loginname": {
|
||||||
"title": "Willkommen zurück!",
|
"title": "Willkommen zurück!",
|
||||||
"description": "Geben Sie Ihre Anmeldedaten ein.",
|
"description": "Geben Sie Ihre Anmeldedaten ein.",
|
||||||
"register": "Neuen Benutzer registrieren"
|
"register": "Neuen Benutzer registrieren",
|
||||||
|
"submit": "Weiter"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"verify": {
|
"verify": {
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
"loginname": {
|
"loginname": {
|
||||||
"title": "Welcome back!",
|
"title": "Welcome back!",
|
||||||
"description": "Enter your login data.",
|
"description": "Enter your login data.",
|
||||||
"register": "Register new user"
|
"register": "Register new user",
|
||||||
|
"submit": "Continue"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"verify": {
|
"verify": {
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
"loginname": {
|
"loginname": {
|
||||||
"title": "¡Bienvenido de nuevo!",
|
"title": "¡Bienvenido de nuevo!",
|
||||||
"description": "Introduce tus datos de acceso.",
|
"description": "Introduce tus datos de acceso.",
|
||||||
"register": "Registrar nuevo usuario"
|
"register": "Registrar nuevo usuario",
|
||||||
|
"submit": "Continuar"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"verify": {
|
"verify": {
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
"loginname": {
|
"loginname": {
|
||||||
"title": "Bentornato!",
|
"title": "Bentornato!",
|
||||||
"description": "Inserisci i tuoi dati di accesso.",
|
"description": "Inserisci i tuoi dati di accesso.",
|
||||||
"register": "Registrati come nuovo utente"
|
"register": "Registrati come nuovo utente",
|
||||||
|
"submit": "Continua"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"verify": {
|
"verify": {
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
"loginname": {
|
"loginname": {
|
||||||
"title": "Witamy ponownie!",
|
"title": "Witamy ponownie!",
|
||||||
"description": "Wprowadź dane logowania.",
|
"description": "Wprowadź dane logowania.",
|
||||||
"register": "Zarejestruj nowego użytkownika"
|
"register": "Zarejestruj nowego użytkownika",
|
||||||
|
"submit": "Kontynuuj"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"verify": {
|
"verify": {
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
"loginname": {
|
"loginname": {
|
||||||
"title": "С возвращением!",
|
"title": "С возвращением!",
|
||||||
"description": "Введите свои данные для входа.",
|
"description": "Введите свои данные для входа.",
|
||||||
"register": "Зарегистрировать нового пользователя"
|
"register": "Зарегистрировать нового пользователя",
|
||||||
|
"submit": "Продолжить"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"verify": {
|
"verify": {
|
||||||
|
@@ -22,7 +22,8 @@
|
|||||||
"loginname": {
|
"loginname": {
|
||||||
"title": "欢迎回来!",
|
"title": "欢迎回来!",
|
||||||
"description": "请输入您的登录信息。",
|
"description": "请输入您的登录信息。",
|
||||||
"register": "注册新用户"
|
"register": "注册新用户",
|
||||||
|
"submit": "继续"
|
||||||
},
|
},
|
||||||
"password": {
|
"password": {
|
||||||
"verify": {
|
"verify": {
|
||||||
|
@@ -26,8 +26,6 @@ const secureHeaders = [
|
|||||||
key: "X-XSS-Protection",
|
key: "X-XSS-Protection",
|
||||||
value: "1; mode=block",
|
value: "1; mode=block",
|
||||||
},
|
},
|
||||||
// img-src vercel.com needed for deploy button,
|
|
||||||
// script-src va.vercel-scripts.com for analytics/vercel scripts
|
|
||||||
{
|
{
|
||||||
key: "Content-Security-Policy",
|
key: "Content-Security-Policy",
|
||||||
value: `${DEFAULT_CSP} frame-ancestors 'none'`,
|
value: `${DEFAULT_CSP} frame-ancestors 'none'`,
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev --turbopack",
|
"dev": "next dev",
|
||||||
"test": "concurrently --timings --kill-others-on-fail 'npm:test:unit' 'npm:test:integration'",
|
"test": "concurrently --timings --kill-others-on-fail 'npm:test:unit' 'npm:test:integration'",
|
||||||
"test:watch": "concurrently --kill-others 'npm:test:unit:watch' 'npm:test:integration:watch'",
|
"test:watch": "concurrently --kill-others 'npm:test:unit:watch' 'npm:test:integration:watch'",
|
||||||
"test:unit": "vitest",
|
"test:unit": "vitest",
|
||||||
@@ -45,10 +45,9 @@
|
|||||||
"clsx": "1.2.1",
|
"clsx": "1.2.1",
|
||||||
"copy-to-clipboard": "^3.3.3",
|
"copy-to-clipboard": "^3.3.3",
|
||||||
"deepmerge": "^4.3.1",
|
"deepmerge": "^4.3.1",
|
||||||
"jose": "^5.3.0",
|
|
||||||
"lucide-react": "0.469.0",
|
"lucide-react": "0.469.0",
|
||||||
"moment": "^2.29.4",
|
"moment": "^2.29.4",
|
||||||
"next": "15.4.0-canary.3",
|
"next": "15.4.0-canary.86",
|
||||||
"next-intl": "^3.25.1",
|
"next-intl": "^3.25.1",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"nice-grpc": "2.0.1",
|
"nice-grpc": "2.0.1",
|
||||||
@@ -56,7 +55,6 @@
|
|||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-dom": "19.1.0",
|
"react-dom": "19.1.0",
|
||||||
"react-hook-form": "7.39.5",
|
"react-hook-form": "7.39.5",
|
||||||
"swr": "^2.2.0",
|
|
||||||
"tinycolor2": "1.4.2",
|
"tinycolor2": "1.4.2",
|
||||||
"uuid": "^11.1.0"
|
"uuid": "^11.1.0"
|
||||||
},
|
},
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { SessionsList } from "@/components/sessions-list";
|
import { SessionsList } from "@/components/sessions-list";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { getAllSessionCookieIds } from "@/lib/cookies";
|
import { getAllSessionCookieIds } from "@/lib/cookies";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import {
|
import {
|
||||||
@@ -9,7 +10,7 @@ import {
|
|||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { UserPlusIcon } from "@heroicons/react/24/outline";
|
import { UserPlusIcon } from "@heroicons/react/24/outline";
|
||||||
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
import { getLocale } from "next-intl/server";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
@@ -33,7 +34,6 @@ export default async function Page(props: {
|
|||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
const locale = getLocale();
|
||||||
const t = await getTranslations({ locale, namespace: "accounts" });
|
|
||||||
|
|
||||||
const requestId = searchParams?.requestId;
|
const requestId = searchParams?.requestId;
|
||||||
const organization = searchParams?.organization;
|
const organization = searchParams?.organization;
|
||||||
@@ -71,8 +71,12 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p mb-6 block">{t("description")}</p>
|
<Translated i18nKey="title" namespace="accounts" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="description" namespace="accounts" />
|
||||||
|
</p>
|
||||||
|
|
||||||
<div className="flex flex-col w-full space-y-2">
|
<div className="flex flex-col w-full space-y-2">
|
||||||
<SessionsList sessions={sessions} requestId={requestId} />
|
<SessionsList sessions={sessions} requestId={requestId} />
|
||||||
@@ -81,7 +85,9 @@ export default async function Page(props: {
|
|||||||
<div className="w-8 h-8 mr-4 flex flex-row justify-center items-center rounded-full bg-black/5 dark:bg-white/5">
|
<div className="w-8 h-8 mr-4 flex flex-row justify-center items-center rounded-full bg-black/5 dark:bg-white/5">
|
||||||
<UserPlusIcon className="h-5 w-5" />
|
<UserPlusIcon className="h-5 w-5" />
|
||||||
</div>
|
</div>
|
||||||
<span className="text-sm">{t("addAnother")}</span>
|
<span className="text-sm">
|
||||||
|
<Translated i18nKey="addAnother" namespace="accounts" />
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -3,6 +3,7 @@ import { BackButton } from "@/components/back-button";
|
|||||||
import { ChooseAuthenticatorToSetup } from "@/components/choose-authenticator-to-setup";
|
import { ChooseAuthenticatorToSetup } from "@/components/choose-authenticator-to-setup";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { SignInWithIdp } from "@/components/sign-in-with-idp";
|
import { SignInWithIdp } from "@/components/sign-in-with-idp";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getSessionCookieById } from "@/lib/cookies";
|
import { getSessionCookieById } from "@/lib/cookies";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
@@ -17,7 +18,7 @@ import {
|
|||||||
listAuthenticationMethodTypes,
|
listAuthenticationMethodTypes,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
import { getLocale } from "next-intl/server";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
|
|
||||||
@@ -26,8 +27,6 @@ export default async function Page(props: {
|
|||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
const locale = getLocale();
|
||||||
const t = await getTranslations({ locale, namespace: "authenticator" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const { loginName, requestId, organization, sessionId } = searchParams;
|
const { loginName, requestId, organization, sessionId } = searchParams;
|
||||||
|
|
||||||
@@ -99,7 +98,11 @@ export default async function Page(props: {
|
|||||||
!sessionWithData.factors ||
|
!sessionWithData.factors ||
|
||||||
!sessionWithData.factors.user
|
!sessionWithData.factors.user
|
||||||
) {
|
) {
|
||||||
return <Alert>{tError("unknownContext")}</Alert>;
|
return (
|
||||||
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const branding = await getBrandingSettings({
|
const branding = await getBrandingSettings({
|
||||||
@@ -165,9 +168,13 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("title")}</h1>
|
<h1>
|
||||||
|
<Translated i18nKey="title" namespace="authenticator" />
|
||||||
|
</h1>
|
||||||
|
|
||||||
<p className="ztdl-p">{t("description")}</p>
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="description" namespace="authenticator" />
|
||||||
|
</p>
|
||||||
|
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
loginName={sessionWithData.factors?.user?.loginName}
|
loginName={sessionWithData.factors?.user?.loginName}
|
||||||
@@ -187,7 +194,9 @@ export default async function Page(props: {
|
|||||||
{loginSettings?.allowExternalIdp && !!identityProviders.length && (
|
{loginSettings?.allowExternalIdp && !!identityProviders.length && (
|
||||||
<>
|
<>
|
||||||
<div className="py-3 flex flex-col">
|
<div className="py-3 flex flex-col">
|
||||||
<p className="ztdl-p text-center">{t("linkWithIDP")}</p>
|
<p className="ztdl-p text-center">
|
||||||
|
<Translated i18nKey="linkWithIDP" namespace="authenticator" />
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SignInWithIdp
|
<SignInWithIdp
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { ConsentScreen } from "@/components/consent";
|
import { ConsentScreen } from "@/components/consent";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import {
|
import {
|
||||||
getBrandingSettings,
|
getBrandingSettings,
|
||||||
@@ -7,22 +8,23 @@ import {
|
|||||||
getDeviceAuthorizationRequest,
|
getDeviceAuthorizationRequest,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale });
|
|
||||||
|
|
||||||
const userCode = searchParams?.user_code;
|
const userCode = searchParams?.user_code;
|
||||||
const requestId = searchParams?.requestId;
|
const requestId = searchParams?.requestId;
|
||||||
const organization = searchParams?.organization;
|
const organization = searchParams?.organization;
|
||||||
|
|
||||||
if (!userCode || !requestId) {
|
if (!userCode || !requestId) {
|
||||||
return <div>{t("error.noUserCode")}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
<Translated i18nKey="noUserCode" namespace="error" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const _headers = await headers();
|
const _headers = await headers();
|
||||||
@@ -34,7 +36,11 @@ export default async function Page(props: {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!deviceAuthorizationRequest) {
|
if (!deviceAuthorizationRequest) {
|
||||||
return <div>{t("error.noDeviceRequest")}</div>;
|
return (
|
||||||
|
<div>
|
||||||
|
<Translated i18nKey="noDeviceRequest" namespace="error" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let defaultOrganization;
|
let defaultOrganization;
|
||||||
@@ -66,15 +72,19 @@ export default async function Page(props: {
|
|||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>
|
<h1>
|
||||||
{t("device.request.title", {
|
<Translated
|
||||||
appName: deviceAuthorizationRequest?.appName,
|
i18nKey="request.title"
|
||||||
})}
|
namespace="device"
|
||||||
|
data={{ appName: deviceAuthorizationRequest?.appName }}
|
||||||
|
/>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p className="ztdl-p">
|
<p className="ztdl-p">
|
||||||
{t("device.request.description", {
|
<Translated
|
||||||
appName: deviceAuthorizationRequest?.appName,
|
i18nKey="request.description"
|
||||||
})}
|
namespace="device"
|
||||||
|
data={{ appName: deviceAuthorizationRequest?.appName }}
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ConsentScreen
|
<ConsentScreen
|
||||||
|
@@ -1,17 +1,15 @@
|
|||||||
import { DeviceCodeForm } from "@/components/device-code-form";
|
import { DeviceCodeForm } from "@/components/device-code-form";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { getBrandingSettings, getDefaultOrg } from "@/lib/zitadel";
|
import { getBrandingSettings, getDefaultOrg } from "@/lib/zitadel";
|
||||||
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "device" });
|
|
||||||
|
|
||||||
const userCode = searchParams?.user_code;
|
const userCode = searchParams?.user_code;
|
||||||
const organization = searchParams?.organization;
|
const organization = searchParams?.organization;
|
||||||
@@ -37,8 +35,12 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("usercode.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("usercode.description")}</p>
|
<Translated i18nKey="usercode.title" namespace="device" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="usercode.description" namespace="device" />
|
||||||
|
</p>
|
||||||
<DeviceCodeForm userCode={userCode}></DeviceCodeForm>
|
<DeviceCodeForm userCode={userCode}></DeviceCodeForm>
|
||||||
</div>
|
</div>
|
||||||
</DynamicTheme>
|
</DynamicTheme>
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { Boundary } from "@/components/boundary";
|
import { Boundary } from "@/components/boundary";
|
||||||
import { Button } from "@/components/button";
|
import { Button } from "@/components/button";
|
||||||
import { useTranslations } from "next-intl";
|
import { Translated } from "@/components/translated";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
|
|
||||||
export default function Error({ error, reset }: any) {
|
export default function Error({ error, reset }: any) {
|
||||||
@@ -10,8 +10,6 @@ export default function Error({ error, reset }: any) {
|
|||||||
console.log("logging error:", error);
|
console.log("logging error:", error);
|
||||||
}, [error]);
|
}, [error]);
|
||||||
|
|
||||||
const t = useTranslations("error");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Boundary labels={["Login Error"]} color="red">
|
<Boundary labels={["Login Error"]} color="red">
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
@@ -19,7 +17,9 @@ export default function Error({ error, reset }: any) {
|
|||||||
<strong className="font-bold">Error:</strong> {error?.message}
|
<strong className="font-bold">Error:</strong> {error?.message}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Button onClick={() => reset()}>{t("tryagain")}</Button>
|
<Button data-i18n-key="error.tryagain" onClick={() => reset()}>
|
||||||
|
<Translated i18nKey="tryagain" namespace="error" />
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Boundary>
|
</Boundary>
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { Alert, AlertType } from "@/components/alert";
|
import { Alert, AlertType } from "@/components/alert";
|
||||||
import { ChooseAuthenticatorToLogin } from "@/components/choose-authenticator-to-login";
|
import { ChooseAuthenticatorToLogin } from "@/components/choose-authenticator-to-login";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import {
|
import {
|
||||||
@@ -11,7 +12,6 @@ import {
|
|||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb";
|
import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb";
|
||||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
@@ -19,8 +19,6 @@ export default async function Page(props: {
|
|||||||
params: Promise<{ provider: string }>;
|
params: Promise<{ provider: string }>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "idp" });
|
|
||||||
|
|
||||||
const { organization, userId } = searchParams;
|
const { organization, userId } = searchParams;
|
||||||
|
|
||||||
@@ -77,8 +75,12 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("loginError.title")}</h1>
|
<h1>
|
||||||
<Alert type={AlertType.ALERT}>{t("loginError.description")}</Alert>
|
<Translated i18nKey="loginError.title" namespace="idp" />
|
||||||
|
</h1>
|
||||||
|
<Alert type={AlertType.ALERT}>
|
||||||
|
<Translated i18nKey="loginError.description" namespace="idp" />
|
||||||
|
</Alert>
|
||||||
|
|
||||||
{userId && authMethods.length && (
|
{userId && authMethods.length && (
|
||||||
<>
|
<>
|
||||||
|
@@ -5,6 +5,7 @@ import { linkingFailed } from "@/components/idps/pages/linking-failed";
|
|||||||
import { linkingSuccess } from "@/components/idps/pages/linking-success";
|
import { linkingSuccess } from "@/components/idps/pages/linking-success";
|
||||||
import { loginFailed } from "@/components/idps/pages/login-failed";
|
import { loginFailed } from "@/components/idps/pages/login-failed";
|
||||||
import { loginSuccess } from "@/components/idps/pages/login-success";
|
import { loginSuccess } from "@/components/idps/pages/login-success";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import {
|
import {
|
||||||
addHuman,
|
addHuman,
|
||||||
@@ -27,7 +28,6 @@ import {
|
|||||||
AddHumanUserRequestSchema,
|
AddHumanUserRequestSchema,
|
||||||
UpdateHumanUserRequestSchema,
|
UpdateHumanUserRequestSchema,
|
||||||
} from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
} from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
const ORG_SUFFIX_REGEX = /(?<=@)(.+)/;
|
const ORG_SUFFIX_REGEX = /(?<=@)(.+)/;
|
||||||
@@ -73,8 +73,6 @@ export default async function Page(props: {
|
|||||||
}) {
|
}) {
|
||||||
const params = await props.params;
|
const params = await props.params;
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "idp" });
|
|
||||||
let { id, token, requestId, organization, link } = searchParams;
|
let { id, token, requestId, organization, link } = searchParams;
|
||||||
const { provider } = params;
|
const { provider } = params;
|
||||||
|
|
||||||
@@ -321,8 +319,12 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("registerSuccess.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("registerSuccess.description")}</p>
|
<Translated i18nKey="registerSuccess.title" namespace="idp" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="registerSuccess.description" namespace="idp" />
|
||||||
|
</p>
|
||||||
<IdpSignin
|
<IdpSignin
|
||||||
userId={newUser.userId}
|
userId={newUser.userId}
|
||||||
idpIntent={{ idpIntentId: id, idpIntentToken: token }}
|
idpIntent={{ idpIntentId: id, idpIntentToken: token }}
|
||||||
|
@@ -1,16 +1,14 @@
|
|||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { SignInWithIdp } from "@/components/sign-in-with-idp";
|
import { SignInWithIdp } from "@/components/sign-in-with-idp";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { getActiveIdentityProviders, getBrandingSettings } from "@/lib/zitadel";
|
import { getActiveIdentityProviders, getBrandingSettings } from "@/lib/zitadel";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "idp" });
|
|
||||||
|
|
||||||
const requestId = searchParams?.requestId;
|
const requestId = searchParams?.requestId;
|
||||||
const organization = searchParams?.organization;
|
const organization = searchParams?.organization;
|
||||||
@@ -33,8 +31,12 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("description")}</p>
|
<Translated i18nKey="title" namespace="idp" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="description" namespace="idp" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{identityProviders && (
|
{identityProviders && (
|
||||||
<SignInWithIdp
|
<SignInWithIdp
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { SignInWithIdp } from "@/components/sign-in-with-idp";
|
import { SignInWithIdp } from "@/components/sign-in-with-idp";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UsernameForm } from "@/components/username-form";
|
import { UsernameForm } from "@/components/username-form";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import {
|
import {
|
||||||
@@ -9,15 +10,12 @@ import {
|
|||||||
getLoginSettings,
|
getLoginSettings,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "loginname" });
|
|
||||||
|
|
||||||
const loginName = searchParams?.loginName;
|
const loginName = searchParams?.loginName;
|
||||||
const requestId = searchParams?.requestId;
|
const requestId = searchParams?.requestId;
|
||||||
@@ -63,8 +61,12 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("title")}</h1>
|
<h1 data-i18n-key="error.tryagain">
|
||||||
<p className="ztdl-p">{t("description")}</p>
|
<Translated i18nKey="title" namespace="loginname" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="description" namespace="loginname" />
|
||||||
|
</p>
|
||||||
|
|
||||||
<UsernameForm
|
<UsernameForm
|
||||||
loginName={loginName}
|
loginName={loginName}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { SessionsClearList } from "@/components/sessions-clear-list";
|
import { SessionsClearList } from "@/components/sessions-clear-list";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { getAllSessionCookieIds } from "@/lib/cookies";
|
import { getAllSessionCookieIds } from "@/lib/cookies";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import {
|
import {
|
||||||
@@ -8,7 +9,6 @@ import {
|
|||||||
listSessions,
|
listSessions,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
async function loadSessions({ serviceUrl }: { serviceUrl: string }) {
|
async function loadSessions({ serviceUrl }: { serviceUrl: string }) {
|
||||||
@@ -30,8 +30,6 @@ export default async function Page(props: {
|
|||||||
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "logout" });
|
|
||||||
|
|
||||||
const organization = searchParams?.organization;
|
const organization = searchParams?.organization;
|
||||||
const postLogoutRedirectUri = searchParams?.post_logout_redirect_uri;
|
const postLogoutRedirectUri = searchParams?.post_logout_redirect_uri;
|
||||||
@@ -67,8 +65,12 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p mb-6 block">{t("description")}</p>
|
<Translated i18nKey="title" namespace="logout" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="description" namespace="logout" />
|
||||||
|
</p>
|
||||||
|
|
||||||
<div className="flex flex-col w-full space-y-2">
|
<div className="flex flex-col w-full space-y-2">
|
||||||
<SessionsClearList
|
<SessionsClearList
|
||||||
|
@@ -1,14 +1,12 @@
|
|||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { getBrandingSettings, getDefaultOrg } from "@/lib/zitadel";
|
import { getBrandingSettings, getDefaultOrg } from "@/lib/zitadel";
|
||||||
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: { searchParams: Promise<any> }) {
|
export default async function Page(props: { searchParams: Promise<any> }) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "logout" });
|
|
||||||
|
|
||||||
const _headers = await headers();
|
const _headers = await headers();
|
||||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||||
@@ -33,8 +31,12 @@ export default async function Page(props: { searchParams: Promise<any> }) {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("success.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p mb-6 block">{t("success.description")}</p>
|
<Translated i18nKey="success.title" namespace="logout" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="success.description" namespace="logout" />
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</DynamicTheme>
|
</DynamicTheme>
|
||||||
);
|
);
|
||||||
|
@@ -2,6 +2,7 @@ import { Alert } from "@/components/alert";
|
|||||||
import { BackButton } from "@/components/back-button";
|
import { BackButton } from "@/components/back-button";
|
||||||
import { ChooseSecondFactor } from "@/components/choose-second-factor";
|
import { ChooseSecondFactor } from "@/components/choose-second-factor";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getSessionCookieById } from "@/lib/cookies";
|
import { getSessionCookieById } from "@/lib/cookies";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
@@ -11,16 +12,12 @@ import {
|
|||||||
getSession,
|
getSession,
|
||||||
listAuthenticationMethodTypes,
|
listAuthenticationMethodTypes,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "mfa" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const { loginName, requestId, organization, sessionId } = searchParams;
|
const { loginName, requestId, organization, sessionId } = searchParams;
|
||||||
|
|
||||||
@@ -90,9 +87,13 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("verify.title")}</h1>
|
<h1>
|
||||||
|
<Translated i18nKey="verify.title" namespace="mfa" />
|
||||||
|
</h1>
|
||||||
|
|
||||||
<p className="ztdl-p">{t("verify.description")}</p>
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="verify.description" namespace="mfa" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{sessionFactors && (
|
{sessionFactors && (
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
@@ -103,7 +104,11 @@ export default async function Page(props: {
|
|||||||
></UserAvatar>
|
></UserAvatar>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!(loginName || sessionId) && <Alert>{tError("unknownContext")}</Alert>}
|
{!(loginName || sessionId) && (
|
||||||
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{sessionFactors ? (
|
{sessionFactors ? (
|
||||||
<ChooseSecondFactor
|
<ChooseSecondFactor
|
||||||
@@ -114,7 +119,9 @@ export default async function Page(props: {
|
|||||||
userMethods={sessionFactors.authMethods ?? []}
|
userMethods={sessionFactors.authMethods ?? []}
|
||||||
></ChooseSecondFactor>
|
></ChooseSecondFactor>
|
||||||
) : (
|
) : (
|
||||||
<Alert>{t("verify.noResults")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="verify.noResults" namespace="mfa" />
|
||||||
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="mt-8 flex w-full flex-row items-center">
|
<div className="mt-8 flex w-full flex-row items-center">
|
||||||
|
@@ -2,6 +2,7 @@ import { Alert } from "@/components/alert";
|
|||||||
import { BackButton } from "@/components/back-button";
|
import { BackButton } from "@/components/back-button";
|
||||||
import { ChooseSecondFactorToSetup } from "@/components/choose-second-factor-to-setup";
|
import { ChooseSecondFactorToSetup } from "@/components/choose-second-factor-to-setup";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getSessionCookieById } from "@/lib/cookies";
|
import { getSessionCookieById } from "@/lib/cookies";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
@@ -15,7 +16,6 @@ import {
|
|||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { Timestamp, timestampDate } from "@zitadel/client";
|
import { Timestamp, timestampDate } from "@zitadel/client";
|
||||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
function isSessionValid(session: Partial<Session>): {
|
function isSessionValid(session: Partial<Session>): {
|
||||||
@@ -38,9 +38,6 @@ export default async function Page(props: {
|
|||||||
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "mfa" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const { loginName, checkAfter, force, requestId, organization, sessionId } =
|
const { loginName, checkAfter, force, requestId, organization, sessionId } =
|
||||||
searchParams;
|
searchParams;
|
||||||
@@ -119,9 +116,13 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("set.title")}</h1>
|
<h1>
|
||||||
|
<Translated i18nKey="set.title" namespace="mfa" />
|
||||||
|
</h1>
|
||||||
|
|
||||||
<p className="ztdl-p">{t("set.description")}</p>
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="set.description" namespace="mfa" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{sessionWithData && (
|
{sessionWithData && (
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
@@ -132,9 +133,17 @@ export default async function Page(props: {
|
|||||||
></UserAvatar>
|
></UserAvatar>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!(loginName || sessionId) && <Alert>{tError("unknownContext")}</Alert>}
|
{!(loginName || sessionId) && (
|
||||||
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{!valid && <Alert>{tError("sessionExpired")}</Alert>}
|
{!valid && (
|
||||||
|
<Alert>
|
||||||
|
<Translated i18nKey="sessionExpired" namespace="error" />
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{isSessionValid(sessionWithData).valid &&
|
{isSessionValid(sessionWithData).valid &&
|
||||||
loginSettings &&
|
loginSettings &&
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { Alert } from "@/components/alert";
|
import { Alert } from "@/components/alert";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { LoginOTP } from "@/components/login-otp";
|
import { LoginOTP } from "@/components/login-otp";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getSessionCookieById } from "@/lib/cookies";
|
import { getSessionCookieById } from "@/lib/cookies";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
@@ -10,7 +11,7 @@ import {
|
|||||||
getLoginSettings,
|
getLoginSettings,
|
||||||
getSession,
|
getSession,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
import { getLocale } from "next-intl/server";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
@@ -20,8 +21,6 @@ export default async function Page(props: {
|
|||||||
const params = await props.params;
|
const params = await props.params;
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
const locale = getLocale();
|
||||||
const t = await getTranslations({ locale, namespace: "otp" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const _headers = await headers();
|
const _headers = await headers();
|
||||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||||
@@ -81,20 +80,30 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("verify.title")}</h1>
|
<h1>
|
||||||
|
<Translated i18nKey="verify.title" namespace="otp" />
|
||||||
|
</h1>
|
||||||
{method === "time-based" && (
|
{method === "time-based" && (
|
||||||
<p className="ztdl-p">{t("verify.totpDescription")}</p>
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="verify.totpDescription" namespace="otp" />
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
{method === "sms" && (
|
{method === "sms" && (
|
||||||
<p className="ztdl-p">{t("verify.smsDescription")}</p>
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="verify.smsDescription" namespace="otp" />
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
{method === "email" && (
|
{method === "email" && (
|
||||||
<p className="ztdl-p">{t("verify.emailDescription")}</p>
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="verify.emailDescription" namespace="otp" />
|
||||||
|
</p>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!session && (
|
{!session && (
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<Alert>{tError("unknownContext")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@ import { BackButton } from "@/components/back-button";
|
|||||||
import { Button, ButtonVariants } from "@/components/button";
|
import { Button, ButtonVariants } from "@/components/button";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { TotpRegister } from "@/components/totp-register";
|
import { TotpRegister } from "@/components/totp-register";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { loadMostRecentSession } from "@/lib/session";
|
import { loadMostRecentSession } from "@/lib/session";
|
||||||
@@ -14,7 +15,6 @@ import {
|
|||||||
registerTOTP,
|
registerTOTP,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { RegisterTOTPResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
import { RegisterTOTPResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
@@ -25,9 +25,6 @@ export default async function Page(props: {
|
|||||||
}) {
|
}) {
|
||||||
const params = await props.params;
|
const params = await props.params;
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "otp" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const { loginName, organization, sessionId, requestId, checkAfter } =
|
const { loginName, organization, sessionId, requestId, checkAfter } =
|
||||||
searchParams;
|
searchParams;
|
||||||
@@ -128,10 +125,14 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("set.title")}</h1>
|
<h1>
|
||||||
|
<Translated i18nKey="set.title" namespace="otp" />
|
||||||
|
</h1>
|
||||||
{!session && (
|
{!session && (
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<Alert>{tError("unknownContext")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -152,7 +153,12 @@ export default async function Page(props: {
|
|||||||
|
|
||||||
{totpResponse && "uri" in totpResponse && "secret" in totpResponse ? (
|
{totpResponse && "uri" in totpResponse && "secret" in totpResponse ? (
|
||||||
<>
|
<>
|
||||||
<p className="ztdl-p">{t("set.totpRegisterDescription")}</p>
|
<p className="ztdl-p">
|
||||||
|
<Translated
|
||||||
|
i18nKey="set.totpRegisterDescription"
|
||||||
|
namespace="otp"
|
||||||
|
/>
|
||||||
|
</p>
|
||||||
<div>
|
<div>
|
||||||
<TotpRegister
|
<TotpRegister
|
||||||
uri={totpResponse.uri as string}
|
uri={totpResponse.uri as string}
|
||||||
@@ -186,7 +192,7 @@ export default async function Page(props: {
|
|||||||
className="self-end"
|
className="self-end"
|
||||||
variant={ButtonVariants.Primary}
|
variant={ButtonVariants.Primary}
|
||||||
>
|
>
|
||||||
{t("set.submit")}
|
<Translated i18nKey="set.submit" namespace="otp" />
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,21 +1,18 @@
|
|||||||
import { Alert } from "@/components/alert";
|
import { Alert } from "@/components/alert";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { LoginPasskey } from "@/components/login-passkey";
|
import { LoginPasskey } from "@/components/login-passkey";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getSessionCookieById } from "@/lib/cookies";
|
import { getSessionCookieById } from "@/lib/cookies";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { loadMostRecentSession } from "@/lib/session";
|
import { loadMostRecentSession } from "@/lib/session";
|
||||||
import { getBrandingSettings, getSession } from "@/lib/zitadel";
|
import { getBrandingSettings, getSession } from "@/lib/zitadel";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "passkey" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const { loginName, altPassword, requestId, organization, sessionId } =
|
const { loginName, altPassword, requestId, organization, sessionId } =
|
||||||
searchParams;
|
searchParams;
|
||||||
@@ -55,7 +52,9 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("verify.title")}</h1>
|
<h1>
|
||||||
|
<Translated i18nKey="verify.title" namespace="passkey" />
|
||||||
|
</h1>
|
||||||
|
|
||||||
{sessionFactors && (
|
{sessionFactors && (
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
@@ -65,9 +64,15 @@ export default async function Page(props: {
|
|||||||
searchParams={searchParams}
|
searchParams={searchParams}
|
||||||
></UserAvatar>
|
></UserAvatar>
|
||||||
)}
|
)}
|
||||||
<p className="ztdl-p mb-6 block">{t("verify.description")}</p>
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="verify.description" namespace="passkey" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{!(loginName || sessionId) && <Alert>{tError("unknownContext")}</Alert>}
|
{!(loginName || sessionId) && (
|
||||||
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{(loginName || sessionId) && (
|
{(loginName || sessionId) && (
|
||||||
<LoginPasskey
|
<LoginPasskey
|
||||||
|
@@ -1,20 +1,17 @@
|
|||||||
import { Alert, AlertType } from "@/components/alert";
|
import { Alert, AlertType } from "@/components/alert";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { RegisterPasskey } from "@/components/register-passkey";
|
import { RegisterPasskey } from "@/components/register-passkey";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { loadMostRecentSession } from "@/lib/session";
|
import { loadMostRecentSession } from "@/lib/session";
|
||||||
import { getBrandingSettings } from "@/lib/zitadel";
|
import { getBrandingSettings } from "@/lib/zitadel";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "passkey" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const { loginName, prompt, organization, requestId, userId } = searchParams;
|
const { loginName, prompt, organization, requestId, userId } = searchParams;
|
||||||
|
|
||||||
@@ -37,7 +34,9 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("set.title")}</h1>
|
<h1>
|
||||||
|
<Translated i18nKey="set.title" namespace="passkey" />
|
||||||
|
</h1>
|
||||||
|
|
||||||
{session && (
|
{session && (
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
@@ -47,24 +46,28 @@ export default async function Page(props: {
|
|||||||
searchParams={searchParams}
|
searchParams={searchParams}
|
||||||
></UserAvatar>
|
></UserAvatar>
|
||||||
)}
|
)}
|
||||||
<p className="ztdl-p mb-6 block">{t("set.description")}</p>
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="set.description" namespace="passkey" />
|
||||||
|
</p>
|
||||||
|
|
||||||
<Alert type={AlertType.INFO}>
|
<Alert type={AlertType.INFO}>
|
||||||
<span>
|
<span>
|
||||||
{t("set.info.description")}
|
<Translated i18nKey="set.info.description" namespace="passkey" />
|
||||||
<a
|
<a
|
||||||
className="text-primary-light-500 dark:text-primary-dark-500 hover:text-primary-light-300 hover:dark:text-primary-dark-300"
|
className="text-primary-light-500 dark:text-primary-dark-500 hover:text-primary-light-300 hover:dark:text-primary-dark-300"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
href="https://zitadel.com/docs/guides/manage/user/reg-create-user#with-passwordless"
|
href="https://zitadel.com/docs/guides/manage/user/reg-create-user#with-passwordless"
|
||||||
>
|
>
|
||||||
{t("set.info.link")}
|
<Translated i18nKey="set.info.link" namespace="passkey" />
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
</Alert>
|
</Alert>
|
||||||
|
|
||||||
{!session && (
|
{!session && (
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<Alert>{tError("unknownContext")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { Alert } from "@/components/alert";
|
import { Alert } from "@/components/alert";
|
||||||
import { ChangePasswordForm } from "@/components/change-password-form";
|
import { ChangePasswordForm } from "@/components/change-password-form";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { loadMostRecentSession } from "@/lib/session";
|
import { loadMostRecentSession } from "@/lib/session";
|
||||||
@@ -9,7 +10,6 @@ import {
|
|||||||
getLoginSettings,
|
getLoginSettings,
|
||||||
getPasswordComplexitySettings,
|
getPasswordComplexitySettings,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
@@ -19,9 +19,6 @@ export default async function Page(props: {
|
|||||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||||
|
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "password" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const { loginName, organization, requestId } = searchParams;
|
const { loginName, organization, requestId } = searchParams;
|
||||||
|
|
||||||
@@ -53,15 +50,21 @@ export default async function Page(props: {
|
|||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>
|
<h1>
|
||||||
{sessionFactors?.factors?.user?.displayName ?? t("change.title")}
|
{sessionFactors?.factors?.user?.displayName ?? (
|
||||||
|
<Translated i18nKey="change.title" namespace="password" />
|
||||||
|
)}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="ztdl-p mb-6 block">{t("change.description")}</p>
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="change.description" namespace="u2f" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{/* show error only if usernames should be shown to be unknown */}
|
{/* show error only if usernames should be shown to be unknown */}
|
||||||
{(!sessionFactors || !loginName) &&
|
{(!sessionFactors || !loginName) &&
|
||||||
!loginSettings?.ignoreUnknownUsernames && (
|
!loginSettings?.ignoreUnknownUsernames && (
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<Alert>{tError("unknownContext")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -86,7 +89,9 @@ export default async function Page(props: {
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<Alert>{tError("failedLoading")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="failedLoading" namespace="error" />
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { Alert } from "@/components/alert";
|
import { Alert } from "@/components/alert";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { PasswordForm } from "@/components/password-form";
|
import { PasswordForm } from "@/components/password-form";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { loadMostRecentSession } from "@/lib/session";
|
import { loadMostRecentSession } from "@/lib/session";
|
||||||
@@ -11,17 +12,12 @@ import {
|
|||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
||||||
import { PasskeysType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
import { PasskeysType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "password" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
let { loginName, organization, requestId, alt } = searchParams;
|
let { loginName, organization, requestId, alt } = searchParams;
|
||||||
|
|
||||||
const _headers = await headers();
|
const _headers = await headers();
|
||||||
@@ -66,15 +62,21 @@ export default async function Page(props: {
|
|||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>
|
<h1>
|
||||||
{sessionFactors?.factors?.user?.displayName ?? t("verify.title")}
|
{sessionFactors?.factors?.user?.displayName ?? (
|
||||||
|
<Translated i18nKey="verify.title" namespace="password" />
|
||||||
|
)}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="ztdl-p mb-6 block">{t("verify.description")}</p>
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="verify.description" namespace="password" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{/* show error only if usernames should be shown to be unknown */}
|
{/* show error only if usernames should be shown to be unknown */}
|
||||||
{(!sessionFactors || !loginName) &&
|
{(!sessionFactors || !loginName) &&
|
||||||
!loginSettings?.ignoreUnknownUsernames && (
|
!loginSettings?.ignoreUnknownUsernames && (
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<Alert>{tError("unknownContext")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { Alert, AlertType } from "@/components/alert";
|
import { Alert, AlertType } from "@/components/alert";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { SetPasswordForm } from "@/components/set-password-form";
|
import { SetPasswordForm } from "@/components/set-password-form";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { loadMostRecentSession } from "@/lib/session";
|
import { loadMostRecentSession } from "@/lib/session";
|
||||||
@@ -12,7 +13,7 @@ import {
|
|||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||||
import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb";
|
import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
import { getLocale } from "next-intl/server";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
@@ -20,8 +21,6 @@ export default async function Page(props: {
|
|||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
const locale = getLocale();
|
||||||
const t = await getTranslations({ locale, namespace: "password" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const { userId, loginName, organization, requestId, code, initial } =
|
const { userId, loginName, organization, requestId, code, initial } =
|
||||||
searchParams;
|
searchParams;
|
||||||
@@ -73,13 +72,21 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{session?.factors?.user?.displayName ?? t("set.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p mb-6 block">{t("set.description")}</p>
|
{session?.factors?.user?.displayName ?? (
|
||||||
|
<Translated i18nKey="set.title" namespace="password" />
|
||||||
|
)}
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="set.description" namespace="password" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{/* show error only if usernames should be shown to be unknown */}
|
{/* show error only if usernames should be shown to be unknown */}
|
||||||
{loginName && !session && !loginSettings?.ignoreUnknownUsernames && (
|
{loginName && !session && !loginSettings?.ignoreUnknownUsernames && (
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<Alert>{tError("unknownContext")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -99,7 +106,11 @@ export default async function Page(props: {
|
|||||||
></UserAvatar>
|
></UserAvatar>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
{!initial && <Alert type={AlertType.INFO}>{t("set.codeSent")}</Alert>}
|
{!initial && (
|
||||||
|
<Alert type={AlertType.INFO}>
|
||||||
|
<Translated i18nKey="set.codeSent" namespace="password" />
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{passwordComplexity &&
|
{passwordComplexity &&
|
||||||
(loginName ?? user?.preferredLoginName) &&
|
(loginName ?? user?.preferredLoginName) &&
|
||||||
@@ -115,7 +126,9 @@ export default async function Page(props: {
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<Alert>{tError("failedLoading")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="failedLoading" namespace="error" />
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,6 +2,7 @@ import { Alert } from "@/components/alert";
|
|||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { RegisterForm } from "@/components/register-form";
|
import { RegisterForm } from "@/components/register-form";
|
||||||
import { SignInWithIdp } from "@/components/sign-in-with-idp";
|
import { SignInWithIdp } from "@/components/sign-in-with-idp";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import {
|
import {
|
||||||
getActiveIdentityProviders,
|
getActiveIdentityProviders,
|
||||||
@@ -13,7 +14,7 @@ import {
|
|||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
||||||
import { PasskeysType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
import { PasskeysType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
import { getLocale } from "next-intl/server";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
@@ -21,8 +22,6 @@ export default async function Page(props: {
|
|||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
const locale = getLocale();
|
||||||
const t = await getTranslations({ locale, namespace: "register" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
let { firstname, lastname, email, organization, requestId } = searchParams;
|
let { firstname, lastname, email, organization, requestId } = searchParams;
|
||||||
|
|
||||||
@@ -70,8 +69,12 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("disabled.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("disabled.description")}</p>
|
<Translated i18nKey="disabled.title" namespace="register" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="disabled.description" namespace="register" />
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</DynamicTheme>
|
</DynamicTheme>
|
||||||
);
|
);
|
||||||
@@ -80,10 +83,18 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("description")}</p>
|
<Translated i18nKey="title" namespace="register" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="description" namespace="register" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{!organization && <Alert>{tError("unknownContext")}</Alert>}
|
{!organization && (
|
||||||
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{legal &&
|
{legal &&
|
||||||
passwordComplexitySettings &&
|
passwordComplexitySettings &&
|
||||||
@@ -107,7 +118,9 @@ export default async function Page(props: {
|
|||||||
{loginSettings?.allowExternalIdp && !!identityProviders.length && (
|
{loginSettings?.allowExternalIdp && !!identityProviders.length && (
|
||||||
<>
|
<>
|
||||||
<div className="py-3 flex flex-col items-center">
|
<div className="py-3 flex flex-col items-center">
|
||||||
<p className="ztdl-p text-center">{t("orUseIDP")}</p>
|
<p className="ztdl-p text-center">
|
||||||
|
<Translated i18nKey="orUseIDP" namespace="register" />
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<SignInWithIdp
|
<SignInWithIdp
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { SetRegisterPasswordForm } from "@/components/set-register-password-form";
|
import { SetRegisterPasswordForm } from "@/components/set-register-password-form";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import {
|
import {
|
||||||
getBrandingSettings,
|
getBrandingSettings,
|
||||||
@@ -9,15 +10,12 @@ import {
|
|||||||
getPasswordComplexitySettings,
|
getPasswordComplexitySettings,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
searchParams: Promise<Record<string | number | symbol, string | undefined>>;
|
||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "register" });
|
|
||||||
|
|
||||||
let { firstname, lastname, email, organization, requestId } = searchParams;
|
let { firstname, lastname, email, organization, requestId } = searchParams;
|
||||||
|
|
||||||
@@ -57,15 +55,23 @@ export default async function Page(props: {
|
|||||||
return missingData ? (
|
return missingData ? (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("missingdata.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("missingdata.description")}</p>
|
<Translated i18nKey="missingdata.title" namespace="register" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="missingdata.description" namespace="register" />
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</DynamicTheme>
|
</DynamicTheme>
|
||||||
) : loginSettings?.allowRegister && loginSettings.allowUsernamePassword ? (
|
) : loginSettings?.allowRegister && loginSettings.allowUsernamePassword ? (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("password.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("description")}</p>
|
<Translated i18nKey="password.title" namespace="register" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="description" namespace="register" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{legal && passwordComplexitySettings && (
|
{legal && passwordComplexitySettings && (
|
||||||
<SetRegisterPasswordForm
|
<SetRegisterPasswordForm
|
||||||
@@ -82,8 +88,12 @@ export default async function Page(props: {
|
|||||||
) : (
|
) : (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("disabled.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("disabled.description")}</p>
|
<Translated i18nKey="disabled.title" namespace="register" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="disabled.description" namespace="register" />
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</DynamicTheme>
|
</DynamicTheme>
|
||||||
);
|
);
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { Alert, AlertType } from "@/components/alert";
|
import { Alert, AlertType } from "@/components/alert";
|
||||||
import { Button, ButtonVariants } from "@/components/button";
|
import { Button, ButtonVariants } from "@/components/button";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import {
|
import {
|
||||||
getMostRecentCookieWithLoginname,
|
getMostRecentCookieWithLoginname,
|
||||||
@@ -14,7 +15,6 @@ import {
|
|||||||
getLoginSettings,
|
getLoginSettings,
|
||||||
getSession,
|
getSession,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
|
|
||||||
@@ -37,8 +37,6 @@ async function loadSessionById(
|
|||||||
|
|
||||||
export default async function Page(props: { searchParams: Promise<any> }) {
|
export default async function Page(props: { searchParams: Promise<any> }) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "signedin" });
|
|
||||||
|
|
||||||
const _headers = await headers();
|
const _headers = await headers();
|
||||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||||
@@ -66,8 +64,12 @@ export default async function Page(props: { searchParams: Promise<any> }) {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("error.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p mb-6 block">{t("error.description")}</p>
|
<Translated i18nKey="error.title" namespace="signedin" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="error.description" namespace="signedin" />
|
||||||
|
</p>
|
||||||
<Alert>{err.message}</Alert>
|
<Alert>{err.message}</Alert>
|
||||||
</div>
|
</div>
|
||||||
</DynamicTheme>
|
</DynamicTheme>
|
||||||
@@ -94,9 +96,15 @@ export default async function Page(props: { searchParams: Promise<any> }) {
|
|||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>
|
<h1>
|
||||||
{t("title", { user: sessionFactors?.factors?.user?.displayName })}
|
<Translated
|
||||||
|
i18nKey="title"
|
||||||
|
namespace="signedin"
|
||||||
|
data={{ user: sessionFactors?.factors?.user?.displayName }}
|
||||||
|
/>
|
||||||
</h1>
|
</h1>
|
||||||
<p className="ztdl-p mb-6 block">{t("description")}</p>
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="description" namespace="signedin" />
|
||||||
|
</p>
|
||||||
|
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
loginName={loginName ?? sessionFactors?.factors?.user?.loginName}
|
loginName={loginName ?? sessionFactors?.factors?.user?.loginName}
|
||||||
@@ -122,7 +130,7 @@ export default async function Page(props: { searchParams: Promise<any> }) {
|
|||||||
className="self-end"
|
className="self-end"
|
||||||
variant={ButtonVariants.Primary}
|
variant={ButtonVariants.Primary}
|
||||||
>
|
>
|
||||||
{t("continue")}
|
<Translated i18nKey="continue" namespace="signedin" />
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
import { Alert } from "@/components/alert";
|
import { Alert } from "@/components/alert";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { LoginPasskey } from "@/components/login-passkey";
|
import { LoginPasskey } from "@/components/login-passkey";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getSessionCookieById } from "@/lib/cookies";
|
import { getSessionCookieById } from "@/lib/cookies";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { loadMostRecentSession } from "@/lib/session";
|
import { loadMostRecentSession } from "@/lib/session";
|
||||||
import { getBrandingSettings, getSession } from "@/lib/zitadel";
|
import { getBrandingSettings, getSession } from "@/lib/zitadel";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
import { getLocale } from "next-intl/server";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
@@ -14,8 +15,6 @@ export default async function Page(props: {
|
|||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
const locale = getLocale();
|
||||||
const t = await getTranslations({ locale, namespace: "u2f" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const { loginName, requestId, sessionId, organization } = searchParams;
|
const { loginName, requestId, sessionId, organization } = searchParams;
|
||||||
|
|
||||||
@@ -59,7 +58,9 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("verify.title")}</h1>
|
<h1>
|
||||||
|
<Translated i18nKey="verify.title" namespace="u2f" />
|
||||||
|
</h1>
|
||||||
|
|
||||||
{sessionFactors && (
|
{sessionFactors && (
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
@@ -69,9 +70,15 @@ export default async function Page(props: {
|
|||||||
searchParams={searchParams}
|
searchParams={searchParams}
|
||||||
></UserAvatar>
|
></UserAvatar>
|
||||||
)}
|
)}
|
||||||
<p className="ztdl-p mb-6 block">{t("verify.description")}</p>
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="verify.description" namespace="u2f" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{!(loginName || sessionId) && <Alert>{tError("unknownContext")}</Alert>}
|
{!(loginName || sessionId) && (
|
||||||
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
|
)}
|
||||||
|
|
||||||
{(loginName || sessionId) && (
|
{(loginName || sessionId) && (
|
||||||
<LoginPasskey
|
<LoginPasskey
|
||||||
|
@@ -1,11 +1,12 @@
|
|||||||
import { Alert } from "@/components/alert";
|
import { Alert } from "@/components/alert";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
import { RegisterU2f } from "@/components/register-u2f";
|
import { RegisterU2f } from "@/components/register-u2f";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { loadMostRecentSession } from "@/lib/session";
|
import { loadMostRecentSession } from "@/lib/session";
|
||||||
import { getBrandingSettings } from "@/lib/zitadel";
|
import { getBrandingSettings } from "@/lib/zitadel";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
import { getLocale } from "next-intl/server";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: {
|
export default async function Page(props: {
|
||||||
@@ -13,8 +14,6 @@ export default async function Page(props: {
|
|||||||
}) {
|
}) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
const locale = getLocale();
|
||||||
const t = await getTranslations({ locale, namespace: "u2f" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const { loginName, organization, requestId, checkAfter } = searchParams;
|
const { loginName, organization, requestId, checkAfter } = searchParams;
|
||||||
|
|
||||||
@@ -37,7 +36,9 @@ export default async function Page(props: {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("set.title")}</h1>
|
<h1>
|
||||||
|
<Translated i18nKey="set.title" namespace="u2f" />
|
||||||
|
</h1>
|
||||||
|
|
||||||
{sessionFactors && (
|
{sessionFactors && (
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
@@ -47,11 +48,16 @@ export default async function Page(props: {
|
|||||||
searchParams={searchParams}
|
searchParams={searchParams}
|
||||||
></UserAvatar>
|
></UserAvatar>
|
||||||
)}
|
)}
|
||||||
<p className="ztdl-p mb-6 block">{t("set.description")}</p>
|
<p className="ztdl-p mb-6 block">
|
||||||
|
{" "}
|
||||||
|
<Translated i18nKey="set.description" namespace="u2f" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{!sessionFactors && (
|
{!sessionFactors && (
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<Alert>{tError("unknownContext")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import { Alert, AlertType } from "@/components/alert";
|
import { Alert, AlertType } from "@/components/alert";
|
||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { VerifyForm } from "@/components/verify-form";
|
import { VerifyForm } from "@/components/verify-form";
|
||||||
import { sendEmailCode, sendInviteEmailCode } from "@/lib/server/verify";
|
import { sendEmailCode, sendInviteEmailCode } from "@/lib/server/verify";
|
||||||
@@ -7,14 +8,12 @@ import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
|||||||
import { loadMostRecentSession } from "@/lib/session";
|
import { loadMostRecentSession } from "@/lib/session";
|
||||||
import { getBrandingSettings, getUserByID } from "@/lib/zitadel";
|
import { getBrandingSettings, getUserByID } from "@/lib/zitadel";
|
||||||
import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb";
|
import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
import { getLocale } from "next-intl/server";
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: { searchParams: Promise<any> }) {
|
export default async function Page(props: { searchParams: Promise<any> }) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
const locale = getLocale();
|
||||||
const t = await getTranslations({ locale, namespace: "verify" });
|
|
||||||
const tError = await getTranslations({ locale, namespace: "error" });
|
|
||||||
|
|
||||||
const { userId, loginName, code, organization, requestId, invite, send } =
|
const { userId, loginName, code, organization, requestId, invite, send } =
|
||||||
searchParams;
|
searchParams;
|
||||||
@@ -121,23 +120,26 @@ export default async function Page(props: { searchParams: Promise<any> }) {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("verify.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p mb-6 block">{t("verify.description")}</p>
|
<Translated i18nKey="verify.title" namespace="verify" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="verify.description" namespace="verify" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{!id && (
|
{!id && (
|
||||||
<>
|
|
||||||
<h1>{t("verify.title")}</h1>
|
|
||||||
<p className="ztdl-p mb-6 block">{t("verify.description")}</p>
|
|
||||||
|
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<Alert>{tError("unknownContext")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="unknownContext" namespace="error" />
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{id && send && (
|
{id && send && (
|
||||||
<div className="py-4 w-full">
|
<div className="py-4 w-full">
|
||||||
<Alert type={AlertType.INFO}>{t("verify.codeSent")}</Alert>
|
<Alert type={AlertType.INFO}>
|
||||||
|
<Translated i18nKey="verify.codeSent" namespace="verify" />
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { DynamicTheme } from "@/components/dynamic-theme";
|
import { DynamicTheme } from "@/components/dynamic-theme";
|
||||||
|
import { Translated } from "@/components/translated";
|
||||||
import { UserAvatar } from "@/components/user-avatar";
|
import { UserAvatar } from "@/components/user-avatar";
|
||||||
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
import { loadMostRecentSession } from "@/lib/session";
|
import { loadMostRecentSession } from "@/lib/session";
|
||||||
@@ -8,13 +9,10 @@ import {
|
|||||||
getUserByID,
|
getUserByID,
|
||||||
} from "@/lib/zitadel";
|
} from "@/lib/zitadel";
|
||||||
import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb";
|
import { HumanUser, User } from "@zitadel/proto/zitadel/user/v2/user_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { headers } from "next/headers";
|
import { headers } from "next/headers";
|
||||||
|
|
||||||
export default async function Page(props: { searchParams: Promise<any> }) {
|
export default async function Page(props: { searchParams: Promise<any> }) {
|
||||||
const searchParams = await props.searchParams;
|
const searchParams = await props.searchParams;
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "verify" });
|
|
||||||
|
|
||||||
const _headers = await headers();
|
const _headers = await headers();
|
||||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||||
@@ -65,8 +63,12 @@ export default async function Page(props: { searchParams: Promise<any> }) {
|
|||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("successTitle")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p mb-6 block">{t("successDescription")}</p>
|
<Translated i18nKey="successTitle" namespace="verify" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p mb-6 block">
|
||||||
|
<Translated i18nKey="successDescription" namespace="verify" />
|
||||||
|
</p>
|
||||||
|
|
||||||
{sessionFactors ? (
|
{sessionFactors ? (
|
||||||
<UserAvatar
|
<UserAvatar
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
import { Boundary } from "@/components/boundary";
|
import { Boundary } from "@/components/boundary";
|
||||||
import { Button } from "@/components/button";
|
import { Button } from "@/components/button";
|
||||||
import { ThemeWrapper } from "@/components/theme-wrapper";
|
import { ThemeWrapper } from "@/components/theme-wrapper";
|
||||||
import { useTranslations } from "next-intl";
|
import { Translated } from "@/components/translated";
|
||||||
|
|
||||||
export default function GlobalError({
|
export default function GlobalError({
|
||||||
error,
|
error,
|
||||||
@@ -12,8 +12,6 @@ export default function GlobalError({
|
|||||||
error: Error & { digest?: string };
|
error: Error & { digest?: string };
|
||||||
reset: () => void;
|
reset: () => void;
|
||||||
}) {
|
}) {
|
||||||
const t = useTranslations("error");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// global-error must include html and body tags
|
// global-error must include html and body tags
|
||||||
<html>
|
<html>
|
||||||
@@ -25,7 +23,9 @@ export default function GlobalError({
|
|||||||
<span className="font-bold">Error:</span> {error?.message}
|
<span className="font-bold">Error:</span> {error?.message}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Button onClick={() => reset()}>{t("tryagain")}</Button>
|
<Button data-i18n-key="error.tryagain" onClick={() => reset()}>
|
||||||
|
<Translated i18nKey="tryagain" namespace="error" />
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Boundary>
|
</Boundary>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { RadioGroup } from "@headlessui/react";
|
import { RadioGroup } from "@headlessui/react";
|
||||||
import { useTranslations } from "next-intl";
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
export enum AuthenticationMethod {
|
export enum AuthenticationMethod {
|
||||||
Passkey = "passkey",
|
Passkey = "passkey",
|
||||||
@@ -20,8 +20,6 @@ export function AuthenticationMethodRadio({
|
|||||||
selected: any;
|
selected: any;
|
||||||
selectionChanged: (value: any) => void;
|
selectionChanged: (value: any) => void;
|
||||||
}) {
|
}) {
|
||||||
const t = useTranslations("register");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="mx-auto w-full max-w-md">
|
<div className="mx-auto w-full max-w-md">
|
||||||
@@ -80,7 +78,18 @@ export function AuthenticationMethodRadio({
|
|||||||
as="p"
|
as="p"
|
||||||
className={`font-medium ${checked ? "" : ""}`}
|
className={`font-medium ${checked ? "" : ""}`}
|
||||||
>
|
>
|
||||||
{t(`methods.${method}`)}
|
{method === AuthenticationMethod.Passkey && (
|
||||||
|
<Translated
|
||||||
|
i18nKey="methods.passkey"
|
||||||
|
namespace="register"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{method === AuthenticationMethod.Password && (
|
||||||
|
<Translated
|
||||||
|
i18nKey="methods.password"
|
||||||
|
namespace="register"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</RadioGroup.Label>
|
</RadioGroup.Label>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@@ -1,11 +1,10 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { Button, ButtonVariants } from "./button";
|
import { Button, ButtonVariants } from "./button";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
export function BackButton() {
|
export function BackButton() {
|
||||||
const t = useTranslations("common");
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
@@ -13,7 +12,7 @@ export function BackButton() {
|
|||||||
type="button"
|
type="button"
|
||||||
variant={ButtonVariants.Secondary}
|
variant={ButtonVariants.Secondary}
|
||||||
>
|
>
|
||||||
{t("back")}
|
<Translated i18nKey="back" namespace="common" />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,6 @@ import {
|
|||||||
import { create } from "@zitadel/client";
|
import { create } from "@zitadel/client";
|
||||||
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||||
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
|
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FieldValues, useForm } from "react-hook-form";
|
import { FieldValues, useForm } from "react-hook-form";
|
||||||
@@ -23,6 +22,7 @@ import { Button, ButtonVariants } from "./button";
|
|||||||
import { TextInput } from "./input";
|
import { TextInput } from "./input";
|
||||||
import { PasswordComplexity } from "./password-complexity";
|
import { PasswordComplexity } from "./password-complexity";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Inputs =
|
type Inputs =
|
||||||
| {
|
| {
|
||||||
@@ -46,7 +46,6 @@ export function ChangePasswordForm({
|
|||||||
requestId,
|
requestId,
|
||||||
organization,
|
organization,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("password");
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { register, handleSubmit, watch, formState } = useForm<Inputs>({
|
const { register, handleSubmit, watch, formState } = useForm<Inputs>({
|
||||||
@@ -203,8 +202,8 @@ export function ChangePasswordForm({
|
|||||||
onClick={handleSubmit(submitChange)}
|
onClick={handleSubmit(submitChange)}
|
||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
|
||||||
{t("change.submit")}
|
<Translated i18nKey="change.submit" namespace="password" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -3,8 +3,8 @@ import {
|
|||||||
PasskeysType,
|
PasskeysType,
|
||||||
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { PASSKEYS, PASSWORD } from "./auth-methods";
|
import { PASSKEYS, PASSWORD } from "./auth-methods";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
authMethods: AuthenticationMethodType[];
|
authMethods: AuthenticationMethodType[];
|
||||||
@@ -17,13 +17,13 @@ export function ChooseAuthenticatorToLogin({
|
|||||||
params,
|
params,
|
||||||
loginSettings,
|
loginSettings,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("idp");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{authMethods.includes(AuthenticationMethodType.PASSWORD) &&
|
{authMethods.includes(AuthenticationMethodType.PASSWORD) &&
|
||||||
loginSettings?.allowUsernamePassword && (
|
loginSettings?.allowUsernamePassword && (
|
||||||
<div className="ztdl-p">Choose an alternative method to login </div>
|
<div className="ztdl-p">
|
||||||
|
<Translated i18nKey="chooseAlternativeMethod" namespace="idp" />
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="grid grid-cols-1 gap-5 w-full pt-4">
|
<div className="grid grid-cols-1 gap-5 w-full pt-4">
|
||||||
{authMethods.includes(AuthenticationMethodType.PASSWORD) &&
|
{authMethods.includes(AuthenticationMethodType.PASSWORD) &&
|
||||||
|
@@ -3,9 +3,9 @@ import {
|
|||||||
PasskeysType,
|
PasskeysType,
|
||||||
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { Alert, AlertType } from "./alert";
|
import { Alert, AlertType } from "./alert";
|
||||||
import { PASSKEYS, PASSWORD } from "./auth-methods";
|
import { PASSKEYS, PASSWORD } from "./auth-methods";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
authMethods: AuthenticationMethodType[];
|
authMethods: AuthenticationMethodType[];
|
||||||
@@ -18,16 +18,23 @@ export function ChooseAuthenticatorToSetup({
|
|||||||
params,
|
params,
|
||||||
loginSettings,
|
loginSettings,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("authenticator");
|
|
||||||
|
|
||||||
if (authMethods.length !== 0) {
|
if (authMethods.length !== 0) {
|
||||||
return <Alert type={AlertType.ALERT}>{t("allSetup")}</Alert>;
|
return (
|
||||||
|
<Alert type={AlertType.ALERT}>
|
||||||
|
<Translated i18nKey="allSetup" namespace="authenticator" />
|
||||||
|
</Alert>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{loginSettings.passkeysType == PasskeysType.NOT_ALLOWED &&
|
{loginSettings.passkeysType == PasskeysType.NOT_ALLOWED &&
|
||||||
!loginSettings.allowUsernamePassword && (
|
!loginSettings.allowUsernamePassword && (
|
||||||
<Alert type={AlertType.ALERT}>{t("noMethodsAvailable")}</Alert>
|
<Alert type={AlertType.ALERT}>
|
||||||
|
<Translated
|
||||||
|
i18nKey="noMethodsAvailable"
|
||||||
|
namespace="authenticator"
|
||||||
|
/>
|
||||||
|
</Alert>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="grid grid-cols-1 gap-5 w-full pt-4">
|
<div className="grid grid-cols-1 gap-5 w-full pt-4">
|
||||||
|
@@ -6,9 +6,9 @@ import {
|
|||||||
SecondFactorType,
|
SecondFactorType,
|
||||||
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
import { AuthenticationMethodType } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { EMAIL, SMS, TOTP, U2F } from "./auth-methods";
|
import { EMAIL, SMS, TOTP, U2F } from "./auth-methods";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
userId: string;
|
userId: string;
|
||||||
@@ -37,7 +37,6 @@ export function ChooseSecondFactorToSetup({
|
|||||||
emailVerified,
|
emailVerified,
|
||||||
force,
|
force,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("mfa");
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const params = new URLSearchParams({});
|
const params = new URLSearchParams({});
|
||||||
|
|
||||||
@@ -112,7 +111,7 @@ export function ChooseSecondFactorToSetup({
|
|||||||
type="button"
|
type="button"
|
||||||
data-testid="reset-button"
|
data-testid="reset-button"
|
||||||
>
|
>
|
||||||
{t("set.skip")}
|
<Translated i18nKey="set.skip" namespace="mfa" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
@@ -8,6 +8,7 @@ import { useState } from "react";
|
|||||||
import { Alert } from "./alert";
|
import { Alert } from "./alert";
|
||||||
import { Button, ButtonVariants } from "./button";
|
import { Button, ButtonVariants } from "./button";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
export function ConsentScreen({
|
export function ConsentScreen({
|
||||||
scope,
|
scope,
|
||||||
@@ -50,7 +51,7 @@ export function ConsentScreen({
|
|||||||
<ul className="list-disc space-y-2 w-full">
|
<ul className="list-disc space-y-2 w-full">
|
||||||
{scopes?.length === 0 && (
|
{scopes?.length === 0 && (
|
||||||
<span className="w-full text-sm flex flex-row items-center bg-background-light-400 dark:bg-background-dark-400 border border-divider-light py-2 px-4 rounded-md transition-all">
|
<span className="w-full text-sm flex flex-row items-center bg-background-light-400 dark:bg-background-dark-400 border border-divider-light py-2 px-4 rounded-md transition-all">
|
||||||
{t("device.scope.openid")}
|
<Translated i18nKey="device.scope.openid" namespace="device" />
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{scopes?.map((s) => {
|
{scopes?.map((s) => {
|
||||||
@@ -73,7 +74,11 @@ export function ConsentScreen({
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p className="ztdl-p text-xs text-left">
|
<p className="ztdl-p text-xs text-left">
|
||||||
{t("device.request.disclaimer", { appName: appName })}
|
<Translated
|
||||||
|
i18nKey="request.disclaimer"
|
||||||
|
namespace="device"
|
||||||
|
data={{ appName: appName }}
|
||||||
|
/>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{error && (
|
{error && (
|
||||||
@@ -91,7 +96,7 @@ export function ConsentScreen({
|
|||||||
data-testid="deny-button"
|
data-testid="deny-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
||||||
{t("device.request.deny")}
|
<Translated i18nKey="device.request.deny" namespace="device" />
|
||||||
</Button>
|
</Button>
|
||||||
<span className="flex-grow"></span>
|
<span className="flex-grow"></span>
|
||||||
|
|
||||||
@@ -102,7 +107,7 @@ export function ConsentScreen({
|
|||||||
className="self-end"
|
className="self-end"
|
||||||
variant={ButtonVariants.Primary}
|
variant={ButtonVariants.Primary}
|
||||||
>
|
>
|
||||||
{t("device.request.submit")}
|
<Translated i18nKey="device.request.submit" namespace="device" />
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { Alert } from "@/components/alert";
|
import { Alert } from "@/components/alert";
|
||||||
import { getDeviceAuthorizationRequest } from "@/lib/server/oidc";
|
import { getDeviceAuthorizationRequest } from "@/lib/server/oidc";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
@@ -10,14 +9,13 @@ import { BackButton } from "./back-button";
|
|||||||
import { Button, ButtonVariants } from "./button";
|
import { Button, ButtonVariants } from "./button";
|
||||||
import { TextInput } from "./input";
|
import { TextInput } from "./input";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Inputs = {
|
type Inputs = {
|
||||||
userCode: string;
|
userCode: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function DeviceCodeForm({ userCode }: { userCode?: string }) {
|
export function DeviceCodeForm({ userCode }: { userCode?: string }) {
|
||||||
const t = useTranslations("verify");
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { register, handleSubmit, formState } = useForm<Inputs>({
|
const { register, handleSubmit, formState } = useForm<Inputs>({
|
||||||
@@ -87,8 +85,8 @@ export function DeviceCodeForm({ userCode }: { userCode?: string }) {
|
|||||||
onClick={handleSubmit(submitCodeAndContinue)}
|
onClick={handleSubmit(submitCodeAndContinue)}
|
||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
|
||||||
{t("verify.submit")}
|
<Translated i18nKey="verify.submit" namespace="verify" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
import { RegisterFormIDPIncomplete } from "@/components/register-form-idp-incomplete";
|
import { RegisterFormIDPIncomplete } from "@/components/register-form-idp-incomplete";
|
||||||
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
||||||
import { AddHumanUserRequest } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
import { AddHumanUserRequest } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { DynamicTheme } from "../../dynamic-theme";
|
import { DynamicTheme } from "../../dynamic-theme";
|
||||||
|
import { Translated } from "../../translated";
|
||||||
|
|
||||||
export async function completeIDP({
|
export async function completeIDP({
|
||||||
idpUserId,
|
idpUserId,
|
||||||
@@ -26,14 +26,15 @@ export async function completeIDP({
|
|||||||
idpIntentToken: string;
|
idpIntentToken: string;
|
||||||
};
|
};
|
||||||
}) {
|
}) {
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "idp" });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("completeRegister.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("completeRegister.description")}</p>
|
<Translated i18nKey="completeRegister.title" namespace="idp" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="completeRegister.description" namespace="idp" />
|
||||||
|
</p>
|
||||||
|
|
||||||
<RegisterFormIDPIncomplete
|
<RegisterFormIDPIncomplete
|
||||||
idpUserId={idpUserId}
|
idpUserId={idpUserId}
|
||||||
|
@@ -1,20 +1,21 @@
|
|||||||
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { Alert, AlertType } from "../../alert";
|
import { Alert, AlertType } from "../../alert";
|
||||||
import { DynamicTheme } from "../../dynamic-theme";
|
import { DynamicTheme } from "../../dynamic-theme";
|
||||||
|
import { Translated } from "../../translated";
|
||||||
|
|
||||||
export async function linkingFailed(
|
export async function linkingFailed(
|
||||||
branding?: BrandingSettings,
|
branding?: BrandingSettings,
|
||||||
error?: string,
|
error?: string,
|
||||||
) {
|
) {
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "idp" });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("linkingError.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("linkingError.description")}</p>
|
<Translated i18nKey="linkingError.title" namespace="idp" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="linkingError.description" namespace="idp" />
|
||||||
|
</p>
|
||||||
{error && (
|
{error && (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
{<Alert type={AlertType.ALERT}>{error}</Alert>}
|
{<Alert type={AlertType.ALERT}>{error}</Alert>}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { DynamicTheme } from "../../dynamic-theme";
|
import { DynamicTheme } from "../../dynamic-theme";
|
||||||
import { IdpSignin } from "../../idp-signin";
|
import { IdpSignin } from "../../idp-signin";
|
||||||
|
import { Translated } from "../../translated";
|
||||||
|
|
||||||
export async function linkingSuccess(
|
export async function linkingSuccess(
|
||||||
userId: string,
|
userId: string,
|
||||||
@@ -9,14 +9,15 @@ export async function linkingSuccess(
|
|||||||
requestId?: string,
|
requestId?: string,
|
||||||
branding?: BrandingSettings,
|
branding?: BrandingSettings,
|
||||||
) {
|
) {
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "idp" });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("linkingSuccess.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("linkingSuccess.description")}</p>
|
<Translated i18nKey="linkingSuccess.title" namespace="idp" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="linkingSuccess.description" namespace="idp" />
|
||||||
|
</p>
|
||||||
|
|
||||||
<IdpSignin
|
<IdpSignin
|
||||||
userId={userId}
|
userId={userId}
|
||||||
|
@@ -1,17 +1,18 @@
|
|||||||
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { Alert, AlertType } from "../../alert";
|
import { Alert, AlertType } from "../../alert";
|
||||||
import { DynamicTheme } from "../../dynamic-theme";
|
import { DynamicTheme } from "../../dynamic-theme";
|
||||||
|
import { Translated } from "../../translated";
|
||||||
|
|
||||||
export async function loginFailed(branding?: BrandingSettings, error?: string) {
|
export async function loginFailed(branding?: BrandingSettings, error?: string) {
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "idp" });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("loginError.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("loginError.description")}</p>
|
<Translated i18nKey="loginError.title" namespace="idp" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="loginError.description" namespace="idp" />
|
||||||
|
</p>
|
||||||
{error && (
|
{error && (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
{<Alert type={AlertType.ALERT}>{error}</Alert>}
|
{<Alert type={AlertType.ALERT}>{error}</Alert>}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
import { BrandingSettings } from "@zitadel/proto/zitadel/settings/v2/branding_settings_pb";
|
||||||
import { getLocale, getTranslations } from "next-intl/server";
|
|
||||||
import { DynamicTheme } from "../../dynamic-theme";
|
import { DynamicTheme } from "../../dynamic-theme";
|
||||||
import { IdpSignin } from "../../idp-signin";
|
import { IdpSignin } from "../../idp-signin";
|
||||||
|
import { Translated } from "../../translated";
|
||||||
|
|
||||||
export async function loginSuccess(
|
export async function loginSuccess(
|
||||||
userId: string,
|
userId: string,
|
||||||
@@ -9,14 +9,15 @@ export async function loginSuccess(
|
|||||||
requestId?: string,
|
requestId?: string,
|
||||||
branding?: BrandingSettings,
|
branding?: BrandingSettings,
|
||||||
) {
|
) {
|
||||||
const locale = getLocale();
|
|
||||||
const t = await getTranslations({ locale, namespace: "idp" });
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DynamicTheme branding={branding}>
|
<DynamicTheme branding={branding}>
|
||||||
<div className="flex flex-col items-center space-y-4">
|
<div className="flex flex-col items-center space-y-4">
|
||||||
<h1>{t("loginSuccess.title")}</h1>
|
<h1>
|
||||||
<p className="ztdl-p">{t("loginSuccess.description")}</p>
|
<Translated i18nKey="loginSuccess.title" namespace="idp" />
|
||||||
|
</h1>
|
||||||
|
<p className="ztdl-p">
|
||||||
|
<Translated i18nKey="loginSuccess.description" namespace="idp" />
|
||||||
|
</p>
|
||||||
|
|
||||||
<IdpSignin
|
<IdpSignin
|
||||||
userId={userId}
|
userId={userId}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from "react";
|
||||||
|
import { Translated } from "../translated";
|
||||||
import { BaseButton, SignInWithIdentityProviderProps } from "./base-button";
|
import { BaseButton, SignInWithIdentityProviderProps } from "./base-button";
|
||||||
|
|
||||||
export const SignInWithApple = forwardRef<
|
export const SignInWithApple = forwardRef<
|
||||||
@@ -9,7 +9,6 @@ export const SignInWithApple = forwardRef<
|
|||||||
SignInWithIdentityProviderProps
|
SignInWithIdentityProviderProps
|
||||||
>(function SignInWithApple(props, ref) {
|
>(function SignInWithApple(props, ref) {
|
||||||
const { children, name, ...restProps } = props;
|
const { children, name, ...restProps } = props;
|
||||||
const t = useTranslations("idp");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseButton {...restProps} ref={ref}>
|
<BaseButton {...restProps} ref={ref}>
|
||||||
@@ -24,7 +23,13 @@ export const SignInWithApple = forwardRef<
|
|||||||
{children ? (
|
{children ? (
|
||||||
children
|
children
|
||||||
) : (
|
) : (
|
||||||
<span className="ml-4">{name ? name : t("signInWithApple")}</span>
|
<span className="ml-4">
|
||||||
|
{name ? (
|
||||||
|
name
|
||||||
|
) : (
|
||||||
|
<Translated i18nKey="signInWithApple" namespace="idp" />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
);
|
);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from "react";
|
||||||
|
import { Translated } from "../translated";
|
||||||
import { BaseButton, SignInWithIdentityProviderProps } from "./base-button";
|
import { BaseButton, SignInWithIdentityProviderProps } from "./base-button";
|
||||||
|
|
||||||
export const SignInWithAzureAd = forwardRef<
|
export const SignInWithAzureAd = forwardRef<
|
||||||
@@ -9,7 +9,6 @@ export const SignInWithAzureAd = forwardRef<
|
|||||||
SignInWithIdentityProviderProps
|
SignInWithIdentityProviderProps
|
||||||
>(function SignInWithAzureAd(props, ref) {
|
>(function SignInWithAzureAd(props, ref) {
|
||||||
const { children, name, ...restProps } = props;
|
const { children, name, ...restProps } = props;
|
||||||
const t = useTranslations("idp");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseButton {...restProps} ref={ref}>
|
<BaseButton {...restProps} ref={ref}>
|
||||||
@@ -30,7 +29,13 @@ export const SignInWithAzureAd = forwardRef<
|
|||||||
{children ? (
|
{children ? (
|
||||||
children
|
children
|
||||||
) : (
|
) : (
|
||||||
<span className="ml-4">{name ? name : t("signInWithAzureAD")}</span>
|
<span className="ml-4">
|
||||||
|
{name ? (
|
||||||
|
name
|
||||||
|
) : (
|
||||||
|
<Translated i18nKey="signInWithAzureAD" namespace="idp" />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
);
|
);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from "react";
|
||||||
|
import { Translated } from "../translated";
|
||||||
import { BaseButton, SignInWithIdentityProviderProps } from "./base-button";
|
import { BaseButton, SignInWithIdentityProviderProps } from "./base-button";
|
||||||
|
|
||||||
function GitHubLogo() {
|
function GitHubLogo() {
|
||||||
@@ -42,7 +42,6 @@ export const SignInWithGithub = forwardRef<
|
|||||||
SignInWithIdentityProviderProps
|
SignInWithIdentityProviderProps
|
||||||
>(function SignInWithGithub(props, ref) {
|
>(function SignInWithGithub(props, ref) {
|
||||||
const { children, name, ...restProps } = props;
|
const { children, name, ...restProps } = props;
|
||||||
const t = useTranslations("idp");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseButton {...restProps} ref={ref}>
|
<BaseButton {...restProps} ref={ref}>
|
||||||
@@ -52,7 +51,13 @@ export const SignInWithGithub = forwardRef<
|
|||||||
{children ? (
|
{children ? (
|
||||||
children
|
children
|
||||||
) : (
|
) : (
|
||||||
<span className="ml-4">{name ? name : t("signInWithGithub")}</span>
|
<span className="ml-4">
|
||||||
|
{name ? (
|
||||||
|
name
|
||||||
|
) : (
|
||||||
|
<Translated i18nKey="signInWithGithub" namespace="idp" />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
);
|
);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from "react";
|
||||||
|
import { Translated } from "../translated";
|
||||||
import { BaseButton, SignInWithIdentityProviderProps } from "./base-button";
|
import { BaseButton, SignInWithIdentityProviderProps } from "./base-button";
|
||||||
|
|
||||||
export const SignInWithGitlab = forwardRef<
|
export const SignInWithGitlab = forwardRef<
|
||||||
@@ -9,7 +9,6 @@ export const SignInWithGitlab = forwardRef<
|
|||||||
SignInWithIdentityProviderProps
|
SignInWithIdentityProviderProps
|
||||||
>(function SignInWithGitlab(props, ref) {
|
>(function SignInWithGitlab(props, ref) {
|
||||||
const { children, name, ...restProps } = props;
|
const { children, name, ...restProps } = props;
|
||||||
const t = useTranslations("idp");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseButton {...restProps} ref={ref}>
|
<BaseButton {...restProps} ref={ref}>
|
||||||
@@ -41,7 +40,13 @@ export const SignInWithGitlab = forwardRef<
|
|||||||
{children ? (
|
{children ? (
|
||||||
children
|
children
|
||||||
) : (
|
) : (
|
||||||
<span className="ml-4">{name ? name : t("signInWithGitlab")}</span>
|
<span className="ml-4">
|
||||||
|
{name ? (
|
||||||
|
name
|
||||||
|
) : (
|
||||||
|
<Translated i18nKey="signInWithGitlab" namespace="idp" />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
);
|
);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from "react";
|
||||||
|
import { Translated } from "../translated";
|
||||||
import { BaseButton, SignInWithIdentityProviderProps } from "./base-button";
|
import { BaseButton, SignInWithIdentityProviderProps } from "./base-button";
|
||||||
|
|
||||||
export const SignInWithGoogle = forwardRef<
|
export const SignInWithGoogle = forwardRef<
|
||||||
@@ -9,7 +9,6 @@ export const SignInWithGoogle = forwardRef<
|
|||||||
SignInWithIdentityProviderProps
|
SignInWithIdentityProviderProps
|
||||||
>(function SignInWithGoogle(props, ref) {
|
>(function SignInWithGoogle(props, ref) {
|
||||||
const { children, name, ...restProps } = props;
|
const { children, name, ...restProps } = props;
|
||||||
const t = useTranslations("idp");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BaseButton {...restProps} ref={ref}>
|
<BaseButton {...restProps} ref={ref}>
|
||||||
@@ -54,7 +53,13 @@ export const SignInWithGoogle = forwardRef<
|
|||||||
{children ? (
|
{children ? (
|
||||||
children
|
children
|
||||||
) : (
|
) : (
|
||||||
<span className="ml-4">{name ? name : t("signInWithGoogle")}</span>
|
<span className="ml-4">
|
||||||
|
{name ? (
|
||||||
|
name
|
||||||
|
) : (
|
||||||
|
<Translated i18nKey="signInWithGoogle" namespace="idp" />
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
);
|
);
|
||||||
|
@@ -6,7 +6,6 @@ import { create } from "@zitadel/client";
|
|||||||
import { RequestChallengesSchema } from "@zitadel/proto/zitadel/session/v2/challenge_pb";
|
import { RequestChallengesSchema } from "@zitadel/proto/zitadel/session/v2/challenge_pb";
|
||||||
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||||
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
@@ -15,6 +14,7 @@ import { BackButton } from "./back-button";
|
|||||||
import { Button, ButtonVariants } from "./button";
|
import { Button, ButtonVariants } from "./button";
|
||||||
import { TextInput } from "./input";
|
import { TextInput } from "./input";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
// either loginName or sessionId must be provided
|
// either loginName or sessionId must be provided
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -42,8 +42,6 @@ export function LoginOTP({
|
|||||||
code,
|
code,
|
||||||
loginSettings,
|
loginSettings,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("otp");
|
|
||||||
|
|
||||||
const [error, setError] = useState<string>("");
|
const [error, setError] = useState<string>("");
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
@@ -223,7 +221,7 @@ export function LoginOTP({
|
|||||||
<Alert type={AlertType.INFO}>
|
<Alert type={AlertType.INFO}>
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
<span className="flex-1 mr-auto text-left">
|
<span className="flex-1 mr-auto text-left">
|
||||||
{t("verify.noCodeReceived")}
|
<Translated i18nKey="verify.noCodeReceived" namespace="otp" />
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
aria-label="Resend OTP Code"
|
aria-label="Resend OTP Code"
|
||||||
@@ -243,7 +241,7 @@ export function LoginOTP({
|
|||||||
}}
|
}}
|
||||||
data-testid="resend-button"
|
data-testid="resend-button"
|
||||||
>
|
>
|
||||||
{t("verify.resendCode")}
|
<Translated i18nKey="verify.resendCode" namespace="otp" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Alert>
|
</Alert>
|
||||||
@@ -277,8 +275,8 @@ export function LoginOTP({
|
|||||||
})}
|
})}
|
||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
|
||||||
{t("verify.submit")}
|
<Translated i18nKey="verify.submit" namespace="otp" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -9,13 +9,13 @@ import {
|
|||||||
UserVerificationRequirement,
|
UserVerificationRequirement,
|
||||||
} from "@zitadel/proto/zitadel/session/v2/challenge_pb";
|
} from "@zitadel/proto/zitadel/session/v2/challenge_pb";
|
||||||
import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
import { Checks } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import { Alert } from "./alert";
|
import { Alert } from "./alert";
|
||||||
import { BackButton } from "./back-button";
|
import { BackButton } from "./back-button";
|
||||||
import { Button, ButtonVariants } from "./button";
|
import { Button, ButtonVariants } from "./button";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
// either loginName or sessionId must be provided
|
// either loginName or sessionId must be provided
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -35,8 +35,6 @@ export function LoginPasskey({
|
|||||||
organization,
|
organization,
|
||||||
login = true,
|
login = true,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("passkey");
|
|
||||||
|
|
||||||
const [error, setError] = useState<string>("");
|
const [error, setError] = useState<string>("");
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
@@ -234,7 +232,7 @@ export function LoginPasskey({
|
|||||||
}}
|
}}
|
||||||
data-testid="password-button"
|
data-testid="password-button"
|
||||||
>
|
>
|
||||||
{t("verify.usePassword")}
|
<Translated i18nKey="verify.usePassword" namespace="passkey" />
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<BackButton />
|
<BackButton />
|
||||||
@@ -273,8 +271,8 @@ export function LoginPasskey({
|
|||||||
}}
|
}}
|
||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
|
||||||
{t("verify.submit")}
|
<Translated i18nKey="verify.submit" namespace="passkey" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -4,7 +4,6 @@ import { resetPassword, sendPassword } from "@/lib/server/password";
|
|||||||
import { create } from "@zitadel/client";
|
import { create } from "@zitadel/client";
|
||||||
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||||
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
@@ -13,6 +12,7 @@ import { BackButton } from "./back-button";
|
|||||||
import { Button, ButtonVariants } from "./button";
|
import { Button, ButtonVariants } from "./button";
|
||||||
import { TextInput } from "./input";
|
import { TextInput } from "./input";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Inputs = {
|
type Inputs = {
|
||||||
password: string;
|
password: string;
|
||||||
@@ -35,8 +35,6 @@ export function PasswordForm({
|
|||||||
promptPasswordless,
|
promptPasswordless,
|
||||||
isAlternative,
|
isAlternative,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("password");
|
|
||||||
|
|
||||||
const { register, handleSubmit, formState } = useForm<Inputs>({
|
const { register, handleSubmit, formState } = useForm<Inputs>({
|
||||||
mode: "onBlur",
|
mode: "onBlur",
|
||||||
});
|
});
|
||||||
@@ -136,7 +134,7 @@ export function PasswordForm({
|
|||||||
disabled={loading}
|
disabled={loading}
|
||||||
data-testid="reset-button"
|
data-testid="reset-button"
|
||||||
>
|
>
|
||||||
{t("verify.resetPassword")}
|
<Translated i18nKey="verify.resetPassword" namespace="password" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -173,8 +171,8 @@ export function PasswordForm({
|
|||||||
onClick={handleSubmit(submitPassword)}
|
onClick={handleSubmit(submitPassword)}
|
||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
|
||||||
{t("verify.submit")}
|
<Translated i18nKey="verify.submit" namespace="password" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { LegalAndSupportSettings } from "@zitadel/proto/zitadel/settings/v2/legal_settings_pb";
|
import { LegalAndSupportSettings } from "@zitadel/proto/zitadel/settings/v2/legal_settings_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Checkbox } from "./checkbox";
|
import { Checkbox } from "./checkbox";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
legal: LegalAndSupportSettings;
|
legal: LegalAndSupportSettings;
|
||||||
@@ -16,7 +16,6 @@ type AcceptanceState = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
|
export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
|
||||||
const t = useTranslations("register");
|
|
||||||
const [acceptanceState, setAcceptanceState] = useState<AcceptanceState>({
|
const [acceptanceState, setAcceptanceState] = useState<AcceptanceState>({
|
||||||
tosAccepted: false,
|
tosAccepted: false,
|
||||||
privacyPolicyAccepted: false,
|
privacyPolicyAccepted: false,
|
||||||
@@ -25,7 +24,7 @@ export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p className="flex flex-row items-center text-text-light-secondary-500 dark:text-text-dark-secondary-500 mt-4 text-sm">
|
<p className="flex flex-row items-center text-text-light-secondary-500 dark:text-text-dark-secondary-500 mt-4 text-sm">
|
||||||
{t("agreeTo")}
|
<Translated i18nKey="agreeTo" namespace="register" />
|
||||||
{legal?.helpLink && (
|
{legal?.helpLink && (
|
||||||
<span>
|
<span>
|
||||||
<Link href={legal.helpLink} target="_blank">
|
<Link href={legal.helpLink} target="_blank">
|
||||||
@@ -66,7 +65,7 @@ export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
|
|||||||
<div className="mr-4 w-[28rem]">
|
<div className="mr-4 w-[28rem]">
|
||||||
<p className="text-sm text-text-light-500 dark:text-text-dark-500">
|
<p className="text-sm text-text-light-500 dark:text-text-dark-500">
|
||||||
<Link href={legal.tosLink} className="underline" target="_blank">
|
<Link href={legal.tosLink} className="underline" target="_blank">
|
||||||
{t("termsOfService")}
|
<Translated i18nKey="termsOfService" namespace="register" />
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
@@ -95,7 +94,7 @@ export function PrivacyPolicyCheckboxes({ legal, onChange }: Props) {
|
|||||||
className="underline"
|
className="underline"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
{t("privacyPolicy")}
|
<Translated i18nKey="privacyPolicy" namespace="register" />
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { registerUserAndLinkToIDP } from "@/lib/server/register";
|
import { registerUserAndLinkToIDP } from "@/lib/server/register";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FieldValues, useForm } from "react-hook-form";
|
import { FieldValues, useForm } from "react-hook-form";
|
||||||
@@ -10,6 +9,7 @@ import { BackButton } from "./back-button";
|
|||||||
import { Button, ButtonVariants } from "./button";
|
import { Button, ButtonVariants } from "./button";
|
||||||
import { TextInput } from "./input";
|
import { TextInput } from "./input";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Inputs =
|
type Inputs =
|
||||||
| {
|
| {
|
||||||
@@ -45,8 +45,6 @@ export function RegisterFormIDPIncomplete({
|
|||||||
idpId,
|
idpId,
|
||||||
idpUserName,
|
idpUserName,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("register");
|
|
||||||
|
|
||||||
const { register, handleSubmit, formState } = useForm<Inputs>({
|
const { register, handleSubmit, formState } = useForm<Inputs>({
|
||||||
mode: "onBlur",
|
mode: "onBlur",
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -149,8 +147,8 @@ export function RegisterFormIDPIncomplete({
|
|||||||
onClick={handleSubmit(submitAndRegister)}
|
onClick={handleSubmit(submitAndRegister)}
|
||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
|
||||||
{t("submit")}
|
<Translated i18nKey="submit" namespace="register" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -6,7 +6,6 @@ import {
|
|||||||
LoginSettings,
|
LoginSettings,
|
||||||
PasskeysType,
|
PasskeysType,
|
||||||
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
} from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FieldValues, useForm } from "react-hook-form";
|
import { FieldValues, useForm } from "react-hook-form";
|
||||||
@@ -21,6 +20,7 @@ import { Button, ButtonVariants } from "./button";
|
|||||||
import { TextInput } from "./input";
|
import { TextInput } from "./input";
|
||||||
import { PrivacyPolicyCheckboxes } from "./privacy-policy-checkboxes";
|
import { PrivacyPolicyCheckboxes } from "./privacy-policy-checkboxes";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Inputs =
|
type Inputs =
|
||||||
| {
|
| {
|
||||||
@@ -51,8 +51,6 @@ export function RegisterForm({
|
|||||||
loginSettings,
|
loginSettings,
|
||||||
idpCount = 0,
|
idpCount = 0,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("register");
|
|
||||||
|
|
||||||
const { register, handleSubmit, formState } = useForm<Inputs>({
|
const { register, handleSubmit, formState } = useForm<Inputs>({
|
||||||
mode: "onBlur",
|
mode: "onBlur",
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -173,7 +171,7 @@ export function RegisterForm({
|
|||||||
loginSettings.passkeysType == PasskeysType.ALLOWED && (
|
loginSettings.passkeysType == PasskeysType.ALLOWED && (
|
||||||
<>
|
<>
|
||||||
<p className="mt-4 ztdl-p mb-6 block text-left">
|
<p className="mt-4 ztdl-p mb-6 block text-left">
|
||||||
{t("selectMethod")}
|
<Translated i18nKey="selectMethod" namespace="register" />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="pb-4">
|
<div className="pb-4">
|
||||||
@@ -184,12 +182,16 @@ export function RegisterForm({
|
|||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{!loginSettings?.allowUsernamePassword &&
|
{!loginSettings?.allowUsernamePassword &&
|
||||||
loginSettings?.passkeysType != PasskeysType.ALLOWED &&
|
loginSettings?.passkeysType !== PasskeysType.ALLOWED &&
|
||||||
(!loginSettings?.allowExternalIdp || !idpCount) && (
|
(!loginSettings?.allowExternalIdp || !idpCount) && (
|
||||||
<div className="py-4">
|
<div className="py-4">
|
||||||
<Alert type={AlertType.INFO}>{t("noMethodAvailableWarning")}</Alert>
|
<Alert type={AlertType.INFO}>
|
||||||
|
<Translated
|
||||||
|
i18nKey="noMethodAvailableWarning"
|
||||||
|
namespace="register"
|
||||||
|
/>
|
||||||
|
</Alert>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -217,7 +219,7 @@ export function RegisterForm({
|
|||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
||||||
{t("submit")}
|
<Translated i18nKey="submit" namespace="register" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -5,7 +5,6 @@ import {
|
|||||||
registerPasskeyLink,
|
registerPasskeyLink,
|
||||||
verifyPasskeyRegistration,
|
verifyPasskeyRegistration,
|
||||||
} from "@/lib/server/passkeys";
|
} from "@/lib/server/passkeys";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
@@ -13,6 +12,7 @@ import { Alert } from "./alert";
|
|||||||
import { BackButton } from "./back-button";
|
import { BackButton } from "./back-button";
|
||||||
import { Button, ButtonVariants } from "./button";
|
import { Button, ButtonVariants } from "./button";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Inputs = {};
|
type Inputs = {};
|
||||||
|
|
||||||
@@ -29,8 +29,6 @@ export function RegisterPasskey({
|
|||||||
organization,
|
organization,
|
||||||
requestId,
|
requestId,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("passkey");
|
|
||||||
|
|
||||||
const { handleSubmit, formState } = useForm<Inputs>({
|
const { handleSubmit, formState } = useForm<Inputs>({
|
||||||
mode: "onBlur",
|
mode: "onBlur",
|
||||||
});
|
});
|
||||||
@@ -198,7 +196,7 @@ export function RegisterPasskey({
|
|||||||
continueAndLogin();
|
continueAndLogin();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("set.skip")}
|
<Translated i18nKey="set.skip" namespace="passkey" />
|
||||||
</Button>
|
</Button>
|
||||||
) : (
|
) : (
|
||||||
<BackButton />
|
<BackButton />
|
||||||
@@ -213,8 +211,8 @@ export function RegisterPasskey({
|
|||||||
onClick={handleSubmit(submitRegisterAndContinue)}
|
onClick={handleSubmit(submitRegisterAndContinue)}
|
||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
|
||||||
{t("set.submit")}
|
<Translated i18nKey="set.submit" namespace="passkey" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -5,13 +5,13 @@ import { getNextUrl } from "@/lib/client";
|
|||||||
import { addU2F, verifyU2F } from "@/lib/server/u2f";
|
import { addU2F, verifyU2F } from "@/lib/server/u2f";
|
||||||
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
import { RegisterU2FResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
import { RegisterU2FResponse } from "@zitadel/proto/zitadel/user/v2/user_service_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Alert } from "./alert";
|
import { Alert } from "./alert";
|
||||||
import { BackButton } from "./back-button";
|
import { BackButton } from "./back-button";
|
||||||
import { Button, ButtonVariants } from "./button";
|
import { Button, ButtonVariants } from "./button";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
loginName?: string;
|
loginName?: string;
|
||||||
@@ -30,8 +30,6 @@ export function RegisterU2f({
|
|||||||
checkAfter,
|
checkAfter,
|
||||||
loginSettings,
|
loginSettings,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("u2f");
|
|
||||||
|
|
||||||
const [error, setError] = useState<string>("");
|
const [error, setError] = useState<string>("");
|
||||||
|
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
@@ -218,8 +216,8 @@ export function RegisterU2f({
|
|||||||
onClick={submitRegisterAndContinue}
|
onClick={submitRegisterAndContinue}
|
||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
|
||||||
{t("set.submit")}
|
<Translated i18nKey="set.submit" namespace="u2f" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -4,11 +4,12 @@ import { clearSession } from "@/lib/server/session";
|
|||||||
import { timestampDate } from "@zitadel/client";
|
import { timestampDate } from "@zitadel/client";
|
||||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import { useLocale, useTranslations } from "next-intl";
|
import { useLocale } from "next-intl";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Avatar } from "./avatar";
|
import { Avatar } from "./avatar";
|
||||||
import { isSessionValid } from "./session-item";
|
import { isSessionValid } from "./session-item";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
export function SessionClearItem({
|
export function SessionClearItem({
|
||||||
session,
|
session,
|
||||||
@@ -17,8 +18,6 @@ export function SessionClearItem({
|
|||||||
session: Session;
|
session: Session;
|
||||||
reload: () => void;
|
reload: () => void;
|
||||||
}) {
|
}) {
|
||||||
const t = useTranslations("logout");
|
|
||||||
|
|
||||||
const currentLocale = useLocale();
|
const currentLocale = useLocale();
|
||||||
moment.locale(currentLocale === "zh" ? "zh-cn" : currentLocale);
|
moment.locale(currentLocale === "zh" ? "zh-cn" : currentLocale);
|
||||||
|
|
||||||
@@ -70,10 +69,13 @@ export function SessionClearItem({
|
|||||||
</span>
|
</span>
|
||||||
{valid ? (
|
{valid ? (
|
||||||
<span className="text-xs opacity-80 text-ellipsis">
|
<span className="text-xs opacity-80 text-ellipsis">
|
||||||
{verifiedAt &&
|
{verifiedAt && (
|
||||||
t("verfiedAt", {
|
<Translated
|
||||||
time: moment(timestampDate(verifiedAt)).fromNow(),
|
i18nKey="verfiedAt"
|
||||||
})}
|
namespace="logout"
|
||||||
|
data={{ time: moment(timestampDate(verifiedAt)).fromNow() }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
verifiedAt && (
|
verifiedAt && (
|
||||||
@@ -89,7 +91,7 @@ export function SessionClearItem({
|
|||||||
<span className="flex-grow"></span>
|
<span className="flex-grow"></span>
|
||||||
<div className="relative flex flex-row items-center">
|
<div className="relative flex flex-row items-center">
|
||||||
<div className="mr-6 px-2 py-[2px] text-xs hidden group-hover:block transition-all text-warn-light-500 dark:text-warn-dark-500 bg-[#ff0000]/10 dark:bg-[#ff0000]/10 rounded-full flex items-center justify-center">
|
<div className="mr-6 px-2 py-[2px] text-xs hidden group-hover:block transition-all text-warn-light-500 dark:text-warn-dark-500 bg-[#ff0000]/10 dark:bg-[#ff0000]/10 rounded-full flex items-center justify-center">
|
||||||
{t("clear")}
|
<Translated i18nKey="clear" namespace="logout" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{valid ? (
|
{valid ? (
|
||||||
|
@@ -3,11 +3,11 @@
|
|||||||
import { clearSession } from "@/lib/server/session";
|
import { clearSession } from "@/lib/server/session";
|
||||||
import { timestampDate } from "@zitadel/client";
|
import { timestampDate } from "@zitadel/client";
|
||||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { redirect, useRouter } from "next/navigation";
|
import { redirect, useRouter } from "next/navigation";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { Alert, AlertType } from "./alert";
|
import { Alert, AlertType } from "./alert";
|
||||||
import { SessionClearItem } from "./session-clear-item";
|
import { SessionClearItem } from "./session-clear-item";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
sessions: Session[];
|
sessions: Session[];
|
||||||
@@ -22,7 +22,6 @@ export function SessionsClearList({
|
|||||||
postLogoutRedirectUri,
|
postLogoutRedirectUri,
|
||||||
organization,
|
organization,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("logout");
|
|
||||||
const [list, setList] = useState<Session[]>(sessions);
|
const [list, setList] = useState<Session[]>(sessions);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
@@ -97,10 +96,14 @@ export function SessionsClearList({
|
|||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
{list.length === 0 && (
|
{list.length === 0 && (
|
||||||
<Alert type={AlertType.INFO}>{t("noResults")}</Alert>
|
<Alert type={AlertType.INFO}>
|
||||||
|
<Translated i18nKey="noResults" namespace="logout" />
|
||||||
|
</Alert>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Alert>{t("noResults")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="noResults" namespace="logout" />
|
||||||
|
</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
import { timestampDate } from "@zitadel/client";
|
import { timestampDate } from "@zitadel/client";
|
||||||
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
import { Session } from "@zitadel/proto/zitadel/session/v2/session_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Alert } from "./alert";
|
import { Alert } from "./alert";
|
||||||
import { SessionItem } from "./session-item";
|
import { SessionItem } from "./session-item";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
sessions: Session[];
|
sessions: Session[];
|
||||||
@@ -13,7 +13,6 @@ type Props = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function SessionsList({ sessions, requestId }: Props) {
|
export function SessionsList({ sessions, requestId }: Props) {
|
||||||
const t = useTranslations("accounts");
|
|
||||||
const [list, setList] = useState<Session[]>(sessions);
|
const [list, setList] = useState<Session[]>(sessions);
|
||||||
return sessions ? (
|
return sessions ? (
|
||||||
<div className="flex flex-col space-y-2">
|
<div className="flex flex-col space-y-2">
|
||||||
@@ -44,6 +43,8 @@ export function SessionsList({ sessions, requestId }: Props) {
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Alert>{t("noResults")}</Alert>
|
<Alert>
|
||||||
|
<Translated i18nKey="noResults" namespace="accounts" />
|
||||||
|
</Alert>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,6 @@ import {
|
|||||||
import { create } from "@zitadel/client";
|
import { create } from "@zitadel/client";
|
||||||
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
import { ChecksSchema } from "@zitadel/proto/zitadel/session/v2/session_service_pb";
|
||||||
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
|
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FieldValues, useForm } from "react-hook-form";
|
import { FieldValues, useForm } from "react-hook-form";
|
||||||
@@ -24,6 +23,7 @@ import { Button, ButtonVariants } from "./button";
|
|||||||
import { TextInput } from "./input";
|
import { TextInput } from "./input";
|
||||||
import { PasswordComplexity } from "./password-complexity";
|
import { PasswordComplexity } from "./password-complexity";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Inputs =
|
type Inputs =
|
||||||
| {
|
| {
|
||||||
@@ -52,8 +52,6 @@ export function SetPasswordForm({
|
|||||||
code,
|
code,
|
||||||
codeRequired,
|
codeRequired,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("password");
|
|
||||||
|
|
||||||
const { register, handleSubmit, watch, formState } = useForm<Inputs>({
|
const { register, handleSubmit, watch, formState } = useForm<Inputs>({
|
||||||
mode: "onBlur",
|
mode: "onBlur",
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -195,7 +193,7 @@ export function SetPasswordForm({
|
|||||||
<Alert type={AlertType.INFO}>
|
<Alert type={AlertType.INFO}>
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
<span className="flex-1 mr-auto text-left">
|
<span className="flex-1 mr-auto text-left">
|
||||||
{t("set.noCodeReceived")}
|
<Translated i18nKey="set.noCodeReceived" namespace="password" />
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
aria-label="Resend OTP Code"
|
aria-label="Resend OTP Code"
|
||||||
@@ -207,7 +205,7 @@ export function SetPasswordForm({
|
|||||||
}}
|
}}
|
||||||
data-testid="resend-button"
|
data-testid="resend-button"
|
||||||
>
|
>
|
||||||
{t("set.resend")}
|
<Translated i18nKey="set.resend" namespace="password" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Alert>
|
</Alert>
|
||||||
@@ -279,8 +277,8 @@ export function SetPasswordForm({
|
|||||||
onClick={handleSubmit(submitPassword)}
|
onClick={handleSubmit(submitPassword)}
|
||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
|
||||||
{t("set.submit")}
|
<Translated i18nKey="set.submit" namespace="password" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -8,7 +8,6 @@ import {
|
|||||||
} from "@/helpers/validators";
|
} from "@/helpers/validators";
|
||||||
import { registerUser } from "@/lib/server/register";
|
import { registerUser } from "@/lib/server/register";
|
||||||
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
|
import { PasswordComplexitySettings } from "@zitadel/proto/zitadel/settings/v2/password_settings_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { FieldValues, useForm } from "react-hook-form";
|
import { FieldValues, useForm } from "react-hook-form";
|
||||||
@@ -18,6 +17,7 @@ import { Button, ButtonVariants } from "./button";
|
|||||||
import { TextInput } from "./input";
|
import { TextInput } from "./input";
|
||||||
import { PasswordComplexity } from "./password-complexity";
|
import { PasswordComplexity } from "./password-complexity";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Inputs =
|
type Inputs =
|
||||||
| {
|
| {
|
||||||
@@ -43,8 +43,6 @@ export function SetRegisterPasswordForm({
|
|||||||
organization,
|
organization,
|
||||||
requestId,
|
requestId,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("register");
|
|
||||||
|
|
||||||
const { register, handleSubmit, watch, formState } = useForm<Inputs>({
|
const { register, handleSubmit, watch, formState } = useForm<Inputs>({
|
||||||
mode: "onBlur",
|
mode: "onBlur",
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -163,8 +161,8 @@ export function SetRegisterPasswordForm({
|
|||||||
onClick={handleSubmit(submitRegister)}
|
onClick={handleSubmit(submitRegister)}
|
||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}{" "}
|
||||||
{t("password.submit")}
|
<Translated i18nKey="password.submit" namespace="register" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -3,7 +3,6 @@
|
|||||||
import { getNextUrl } from "@/lib/client";
|
import { getNextUrl } from "@/lib/client";
|
||||||
import { verifyTOTP } from "@/lib/server/verify";
|
import { verifyTOTP } from "@/lib/server/verify";
|
||||||
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { QRCodeSVG } from "qrcode.react";
|
import { QRCodeSVG } from "qrcode.react";
|
||||||
@@ -14,6 +13,7 @@ import { Button, ButtonVariants } from "./button";
|
|||||||
import { CopyToClipboard } from "./copy-to-clipboard";
|
import { CopyToClipboard } from "./copy-to-clipboard";
|
||||||
import { TextInput } from "./input";
|
import { TextInput } from "./input";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Inputs = {
|
type Inputs = {
|
||||||
code: string;
|
code: string;
|
||||||
@@ -39,8 +39,6 @@ export function TotpRegister({
|
|||||||
checkAfter,
|
checkAfter,
|
||||||
loginSettings,
|
loginSettings,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("otp");
|
|
||||||
|
|
||||||
const [error, setError] = useState<string>("");
|
const [error, setError] = useState<string>("");
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -148,7 +146,7 @@ export function TotpRegister({
|
|||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
||||||
{t("set.submit")}
|
<Translated i18nKey="set.submit" namespace="otp" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
23
apps/login/src/components/translated.tsx
Normal file
23
apps/login/src/components/translated.tsx
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
|
export function Translated({
|
||||||
|
i18nKey,
|
||||||
|
children,
|
||||||
|
namespace,
|
||||||
|
data,
|
||||||
|
...props
|
||||||
|
}: {
|
||||||
|
i18nKey: string;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
namespace?: string;
|
||||||
|
data?: any;
|
||||||
|
} & React.HTMLAttributes<HTMLSpanElement>) {
|
||||||
|
const t = useTranslations(namespace);
|
||||||
|
const helperKey = `${namespace ? `${namespace}.` : ""}${i18nKey}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span data-i18n-key={helperKey} {...props}>
|
||||||
|
{t(i18nKey, data)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { sendLoginname } from "@/lib/server/loginname";
|
import { sendLoginname } from "@/lib/server/loginname";
|
||||||
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { ReactNode, useEffect, useState } from "react";
|
import { ReactNode, useEffect, useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
@@ -11,6 +10,7 @@ import { BackButton } from "./back-button";
|
|||||||
import { Button, ButtonVariants } from "./button";
|
import { Button, ButtonVariants } from "./button";
|
||||||
import { TextInput } from "./input";
|
import { TextInput } from "./input";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Inputs = {
|
type Inputs = {
|
||||||
loginName: string;
|
loginName: string;
|
||||||
@@ -37,7 +37,6 @@ export function UsernameForm({
|
|||||||
allowRegister,
|
allowRegister,
|
||||||
children,
|
children,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("loginname");
|
|
||||||
const { register, handleSubmit, formState } = useForm<Inputs>({
|
const { register, handleSubmit, formState } = useForm<Inputs>({
|
||||||
mode: "onBlur",
|
mode: "onBlur",
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@@ -127,7 +126,7 @@ export function UsernameForm({
|
|||||||
disabled={loading}
|
disabled={loading}
|
||||||
data-testid="register-button"
|
data-testid="register-button"
|
||||||
>
|
>
|
||||||
{t("register")}
|
<Translated i18nKey="register" namespace="loginname" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -152,7 +151,7 @@ export function UsernameForm({
|
|||||||
onClick={handleSubmit((e) => submitLoginName(e, organization))}
|
onClick={handleSubmit((e) => submitLoginName(e, organization))}
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
||||||
continue
|
<Translated i18nKey="submit" namespace="loginname" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
import { Alert, AlertType } from "@/components/alert";
|
import { Alert, AlertType } from "@/components/alert";
|
||||||
import { resendVerification, sendVerification } from "@/lib/server/verify";
|
import { resendVerification, sendVerification } from "@/lib/server/verify";
|
||||||
import { useTranslations } from "next-intl";
|
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from "react-hook-form";
|
||||||
@@ -10,6 +9,7 @@ import { BackButton } from "./back-button";
|
|||||||
import { Button, ButtonVariants } from "./button";
|
import { Button, ButtonVariants } from "./button";
|
||||||
import { TextInput } from "./input";
|
import { TextInput } from "./input";
|
||||||
import { Spinner } from "./spinner";
|
import { Spinner } from "./spinner";
|
||||||
|
import { Translated } from "./translated";
|
||||||
|
|
||||||
type Inputs = {
|
type Inputs = {
|
||||||
code: string;
|
code: string;
|
||||||
@@ -32,8 +32,6 @@ export function VerifyForm({
|
|||||||
code,
|
code,
|
||||||
isInvite,
|
isInvite,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const t = useTranslations("verify");
|
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { register, handleSubmit, formState } = useForm<Inputs>({
|
const { register, handleSubmit, formState } = useForm<Inputs>({
|
||||||
@@ -117,7 +115,7 @@ export function VerifyForm({
|
|||||||
<Alert type={AlertType.INFO}>
|
<Alert type={AlertType.INFO}>
|
||||||
<div className="flex flex-row">
|
<div className="flex flex-row">
|
||||||
<span className="flex-1 mr-auto text-left">
|
<span className="flex-1 mr-auto text-left">
|
||||||
{t("verify.noCodeReceived")}
|
<Translated i18nKey="verify.noCodeReceived" namespace="verify" />
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
aria-label="Resend Code"
|
aria-label="Resend Code"
|
||||||
@@ -129,7 +127,7 @@ export function VerifyForm({
|
|||||||
}}
|
}}
|
||||||
data-testid="resend-button"
|
data-testid="resend-button"
|
||||||
>
|
>
|
||||||
{t("verify.resendCode")}
|
<Translated i18nKey="verify.resendCode" namespace="verify" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</Alert>
|
</Alert>
|
||||||
@@ -161,7 +159,7 @@ export function VerifyForm({
|
|||||||
data-testid="submit-button"
|
data-testid="submit-button"
|
||||||
>
|
>
|
||||||
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
{loading && <Spinner className="h-5 w-5 mr-2" />}
|
||||||
{t("verify.submit")}
|
<Translated i18nKey="verify.submit" namespace="verify" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
@@ -1,4 +1,7 @@
|
|||||||
import { LANGS, LANGUAGE_COOKIE_NAME, LANGUAGE_HEADER_NAME } from "@/lib/i18n";
|
import { LANGS, LANGUAGE_COOKIE_NAME, LANGUAGE_HEADER_NAME } from "@/lib/i18n";
|
||||||
|
import { getServiceUrlFromHeaders } from "@/lib/service-url";
|
||||||
|
import { getHostedLoginTranslation } from "@/lib/zitadel";
|
||||||
|
import { JsonObject } from "@zitadel/client";
|
||||||
import deepmerge from "deepmerge";
|
import deepmerge from "deepmerge";
|
||||||
import { getRequestConfig } from "next-intl/server";
|
import { getRequestConfig } from "next-intl/server";
|
||||||
import { cookies, headers } from "next/headers";
|
import { cookies, headers } from "next/headers";
|
||||||
@@ -9,6 +12,26 @@ export default getRequestConfig(async () => {
|
|||||||
|
|
||||||
let locale: string = fallback;
|
let locale: string = fallback;
|
||||||
|
|
||||||
|
const _headers = await headers();
|
||||||
|
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||||
|
|
||||||
|
const i18nOrganization = _headers.get("x-zitadel-i18n-organization") || ""; // You may need to set this header in middleware
|
||||||
|
console.log("i18nOrganization:", i18nOrganization);
|
||||||
|
let translations: JsonObject | {} = {};
|
||||||
|
try {
|
||||||
|
const i18nJSON = await getHostedLoginTranslation({
|
||||||
|
serviceUrl,
|
||||||
|
locale,
|
||||||
|
organization: i18nOrganization,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (i18nJSON) {
|
||||||
|
translations = i18nJSON;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn("Error fetching custom translations:", error);
|
||||||
|
}
|
||||||
|
|
||||||
const languageHeader = await (await headers()).get(LANGUAGE_HEADER_NAME);
|
const languageHeader = await (await headers()).get(LANGUAGE_HEADER_NAME);
|
||||||
if (languageHeader) {
|
if (languageHeader) {
|
||||||
const headerLocale = languageHeader.split(",")[0].split("-")[0]; // Extract the language code
|
const headerLocale = languageHeader.split(",")[0].split("-")[0]; // Extract the language code
|
||||||
@@ -24,12 +47,13 @@ export default getRequestConfig(async () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const userMessages = (await import(`../../locales/${locale}.json`)).default;
|
const customMessages = translations;
|
||||||
|
const localeMessages = (await import(`../../locales/${locale}.json`)).default;
|
||||||
const fallbackMessages = (await import(`../../locales/${fallback}.json`))
|
const fallbackMessages = (await import(`../../locales/${fallback}.json`))
|
||||||
.default;
|
.default;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
locale,
|
locale,
|
||||||
messages: deepmerge(fallbackMessages, userMessages),
|
messages: deepmerge.all([fallbackMessages, localeMessages, customMessages]),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@@ -59,6 +59,42 @@ 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) => {
|
||||||
|
console.log(resp);
|
||||||
|
return resp.translations ? resp.translations : undefined;
|
||||||
|
});
|
||||||
|
|
||||||
|
return useCache ? cacheWrapper(callback) : callback;
|
||||||
|
}
|
||||||
|
|
||||||
export async function getBrandingSettings({
|
export async function getBrandingSettings({
|
||||||
serviceUrl,
|
serviceUrl,
|
||||||
organization,
|
organization,
|
||||||
|
@@ -10,21 +10,51 @@ export const config = {
|
|||||||
"/oidc/:path*",
|
"/oidc/:path*",
|
||||||
"/idps/callback/:path*",
|
"/idps/callback/:path*",
|
||||||
"/saml/:path*",
|
"/saml/:path*",
|
||||||
|
"/:path*",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function middleware(request: NextRequest) {
|
export async function middleware(request: NextRequest) {
|
||||||
|
// Add the original URL as a header to all requests
|
||||||
|
const requestHeaders = new Headers(request.headers);
|
||||||
|
|
||||||
|
// Extract "organization" search param from the URL and set it as a header if available
|
||||||
|
const organization = request.nextUrl.searchParams.get("organization");
|
||||||
|
if (organization) {
|
||||||
|
requestHeaders.set("x-zitadel-i18n-organization", organization);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only run the rest of the logic for the original matcher paths
|
||||||
|
const matchedPaths = [
|
||||||
|
"/.well-known/",
|
||||||
|
"/oauth/",
|
||||||
|
"/oidc/",
|
||||||
|
"/idps/callback/",
|
||||||
|
"/saml/",
|
||||||
|
];
|
||||||
|
|
||||||
|
const isMatched = matchedPaths.some((prefix) =>
|
||||||
|
request.nextUrl.pathname.startsWith(prefix),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isMatched) {
|
||||||
|
// For all other routes, just add the header and continue
|
||||||
|
return NextResponse.next({
|
||||||
|
request: { headers: requestHeaders },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// escape proxy if the environment is setup for multitenancy
|
// escape proxy if the environment is setup for multitenancy
|
||||||
if (!process.env.ZITADEL_API_URL || !process.env.ZITADEL_SERVICE_USER_TOKEN) {
|
if (!process.env.ZITADEL_API_URL || !process.env.ZITADEL_SERVICE_USER_TOKEN) {
|
||||||
return NextResponse.next();
|
return NextResponse.next({
|
||||||
|
request: { headers: requestHeaders },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const _headers = await headers();
|
const _headers = await headers();
|
||||||
|
|
||||||
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
const { serviceUrl } = getServiceUrlFromHeaders(_headers);
|
||||||
|
|
||||||
// Call the /security route handler
|
// Call the /security route handler
|
||||||
// TODO check this on cloud run deployment
|
|
||||||
const securityResponse = await fetch(`${request.nextUrl.origin}/security`);
|
const securityResponse = await fetch(`${request.nextUrl.origin}/security`);
|
||||||
|
|
||||||
if (!securityResponse.ok) {
|
if (!securityResponse.ok) {
|
||||||
@@ -32,7 +62,9 @@ export async function middleware(request: NextRequest) {
|
|||||||
"Failed to fetch security settings:",
|
"Failed to fetch security settings:",
|
||||||
securityResponse.statusText,
|
securityResponse.statusText,
|
||||||
);
|
);
|
||||||
return NextResponse.next(); // Fallback if the request fails
|
return NextResponse.next({
|
||||||
|
request: { headers: requestHeaders },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const { settings: securitySettings } = await securityResponse.json();
|
const { settings: securitySettings } = await securityResponse.json();
|
||||||
@@ -41,13 +73,8 @@ export async function middleware(request: NextRequest) {
|
|||||||
.replace("https://", "")
|
.replace("https://", "")
|
||||||
.replace("http://", "");
|
.replace("http://", "");
|
||||||
|
|
||||||
const requestHeaders = new Headers(request.headers);
|
// Add additional headers as before
|
||||||
|
|
||||||
// this is a workaround for the next.js server not forwarding the host header
|
|
||||||
// requestHeaders.set("x-zitadel-forwarded", `host="${request.nextUrl.host}"`);
|
|
||||||
requestHeaders.set("x-zitadel-public-host", `${request.nextUrl.host}`);
|
requestHeaders.set("x-zitadel-public-host", `${request.nextUrl.host}`);
|
||||||
|
|
||||||
// this is a workaround for the next.js server not forwarding the host header
|
|
||||||
requestHeaders.set("x-zitadel-instance-host", instanceHost);
|
requestHeaders.set("x-zitadel-instance-host", instanceHost);
|
||||||
|
|
||||||
const responseHeaders = new Headers();
|
const responseHeaders = new Headers();
|
||||||
@@ -55,7 +82,6 @@ export async function middleware(request: NextRequest) {
|
|||||||
responseHeaders.set("Access-Control-Allow-Headers", "*");
|
responseHeaders.set("Access-Control-Allow-Headers", "*");
|
||||||
|
|
||||||
if (securitySettings?.embeddedIframe?.enabled) {
|
if (securitySettings?.embeddedIframe?.enabled) {
|
||||||
securitySettings.embeddedIframe.allowedOrigins;
|
|
||||||
responseHeaders.set(
|
responseHeaders.set(
|
||||||
"Content-Security-Policy",
|
"Content-Security-Policy",
|
||||||
`${DEFAULT_CSP} frame-ancestors ${securitySettings.embeddedIframe.allowedOrigins.join(" ")};`,
|
`${DEFAULT_CSP} frame-ancestors ${securitySettings.embeddedIframe.allowedOrigins.join(" ")};`,
|
||||||
|
209
pnpm-lock.yaml
generated
209
pnpm-lock.yaml
generated
@@ -85,7 +85,7 @@ importers:
|
|||||||
version: 0.5.7(tailwindcss@3.4.14)
|
version: 0.5.7(tailwindcss@3.4.14)
|
||||||
'@vercel/analytics':
|
'@vercel/analytics':
|
||||||
specifier: ^1.2.2
|
specifier: ^1.2.2
|
||||||
version: 1.3.1(next@15.4.0-canary.3(@babel/core@7.26.10)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react@19.1.0)
|
version: 1.3.1(next@15.4.0-canary.86(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react@19.1.0)
|
||||||
'@zitadel/client':
|
'@zitadel/client':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/zitadel-client
|
version: link:../../packages/zitadel-client
|
||||||
@@ -101,9 +101,6 @@ importers:
|
|||||||
deepmerge:
|
deepmerge:
|
||||||
specifier: ^4.3.1
|
specifier: ^4.3.1
|
||||||
version: 4.3.1
|
version: 4.3.1
|
||||||
jose:
|
|
||||||
specifier: ^5.3.0
|
|
||||||
version: 5.8.0
|
|
||||||
lucide-react:
|
lucide-react:
|
||||||
specifier: 0.469.0
|
specifier: 0.469.0
|
||||||
version: 0.469.0(react@19.1.0)
|
version: 0.469.0(react@19.1.0)
|
||||||
@@ -111,14 +108,14 @@ importers:
|
|||||||
specifier: ^2.29.4
|
specifier: ^2.29.4
|
||||||
version: 2.30.1
|
version: 2.30.1
|
||||||
next:
|
next:
|
||||||
specifier: 15.4.0-canary.3
|
specifier: 15.4.0-canary.86
|
||||||
version: 15.4.0-canary.3(@babel/core@7.26.10)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0)
|
version: 15.4.0-canary.86(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0)
|
||||||
next-intl:
|
next-intl:
|
||||||
specifier: ^3.25.1
|
specifier: ^3.25.1
|
||||||
version: 3.25.1(next@15.4.0-canary.3(@babel/core@7.26.10)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react@19.1.0)
|
version: 3.26.5(next@15.4.0-canary.86(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react@19.1.0)
|
||||||
next-themes:
|
next-themes:
|
||||||
specifier: ^0.2.1
|
specifier: ^0.2.1
|
||||||
version: 0.2.1(next@15.4.0-canary.3(@babel/core@7.26.10)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
version: 0.2.1(next@15.4.0-canary.86(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
|
||||||
nice-grpc:
|
nice-grpc:
|
||||||
specifier: 2.0.1
|
specifier: 2.0.1
|
||||||
version: 2.0.1
|
version: 2.0.1
|
||||||
@@ -134,9 +131,6 @@ importers:
|
|||||||
react-hook-form:
|
react-hook-form:
|
||||||
specifier: 7.39.5
|
specifier: 7.39.5
|
||||||
version: 7.39.5(react@19.1.0)
|
version: 7.39.5(react@19.1.0)
|
||||||
swr:
|
|
||||||
specifier: ^2.2.0
|
|
||||||
version: 2.2.5(react@19.1.0)
|
|
||||||
tinycolor2:
|
tinycolor2:
|
||||||
specifier: 1.4.2
|
specifier: 1.4.2
|
||||||
version: 1.4.2
|
version: 1.4.2
|
||||||
@@ -807,9 +801,6 @@ packages:
|
|||||||
'@formatjs/icu-skeleton-parser@1.8.8':
|
'@formatjs/icu-skeleton-parser@1.8.8':
|
||||||
resolution: {integrity: sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==}
|
resolution: {integrity: sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==}
|
||||||
|
|
||||||
'@formatjs/intl-localematcher@0.5.4':
|
|
||||||
resolution: {integrity: sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==}
|
|
||||||
|
|
||||||
'@formatjs/intl-localematcher@0.5.8':
|
'@formatjs/intl-localematcher@0.5.8':
|
||||||
resolution: {integrity: sha512-I+WDNWWJFZie+jkfkiK5Mp4hEDyRSEvmyfYadflOno/mmKJKcB17fEpEH0oJu/OWhhCJ8kJBDz2YMd/6cDl7Mg==}
|
resolution: {integrity: sha512-I+WDNWWJFZie+jkfkiK5Mp4hEDyRSEvmyfYadflOno/mmKJKcB17fEpEH0oJu/OWhhCJ8kJBDz2YMd/6cDl7Mg==}
|
||||||
|
|
||||||
@@ -998,56 +989,56 @@ packages:
|
|||||||
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
|
resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
'@next/env@15.4.0-canary.3':
|
'@next/env@15.4.0-canary.86':
|
||||||
resolution: {integrity: sha512-lu4pB2e3Z/d+B0rxEm9YuQMb57Hd96iJUBZgVlcRNemlIryr0GByu17kvN6nBk3JjbWL8h+MW90stpGzGdhbqg==}
|
resolution: {integrity: sha512-WPrEvwqHnjeLx05ncJvqizbBJJFlQGRbxzOnL/pZWKzo19auM9x5Se87P27+E/D/d6jJS801l+thF85lfobAZQ==}
|
||||||
|
|
||||||
'@next/eslint-plugin-next@14.2.18':
|
'@next/eslint-plugin-next@14.2.18':
|
||||||
resolution: {integrity: sha512-KyYTbZ3GQwWOjX3Vi1YcQbekyGP0gdammb7pbmmi25HBUCINzDReyrzCMOJIeZisK1Q3U6DT5Rlc4nm2/pQeXA==}
|
resolution: {integrity: sha512-KyYTbZ3GQwWOjX3Vi1YcQbekyGP0gdammb7pbmmi25HBUCINzDReyrzCMOJIeZisK1Q3U6DT5Rlc4nm2/pQeXA==}
|
||||||
|
|
||||||
'@next/swc-darwin-arm64@15.4.0-canary.3':
|
'@next/swc-darwin-arm64@15.4.0-canary.86':
|
||||||
resolution: {integrity: sha512-w9u8IpwLb/JS7HzHLt24smP4FxIYMgciOtYNUCognO1xh1XZfqqjDIrRAXDuuYDPKrc1i2EvI24R5eDTz7EYMQ==}
|
resolution: {integrity: sha512-1ofBmzjPkmoMdM+dXvybZ/Roq8HRo0sFzcwXk7/FJNOufuwyK+QKdSpLE7pHlPR7ZREqfEMj61ONO+gAK+zOJw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@next/swc-darwin-x64@15.4.0-canary.3':
|
'@next/swc-darwin-x64@15.4.0-canary.86':
|
||||||
resolution: {integrity: sha512-5pL1hBRw8h1XeArzWYjCDERtRFIfrMAz1Nq9m1np8FrTuHclE7xitKKfOJqqmBbO9dWtnZIfA8lZl9bdlNEUZg==}
|
resolution: {integrity: sha512-WCKSrllvwzYi4TgrSdgxKSOF2nhieeaWWOeGucn0OXy50uOAamr0HwP5OaIBCx3oRar4w66gvs4IrdTdMedeJA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@next/swc-linux-arm64-gnu@15.4.0-canary.3':
|
'@next/swc-linux-arm64-gnu@15.4.0-canary.86':
|
||||||
resolution: {integrity: sha512-vx6cU4jKoecF2QZw3CQqJrzb+D0WhNzHHoWUN8O+YKPnX0oG4wEtAQWSWisxKjNrU1U4TiraOql0nOQBUOKwaQ==}
|
resolution: {integrity: sha512-8qn7DJVNFjhEIDo2ts0YCsO7g+vJjPWh8Ur8lBK3XspeX0BPsF4s+YmgidrpzRXeIfoo2uYLkkXcy/57CVDblw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-arm64-musl@15.4.0-canary.3':
|
'@next/swc-linux-arm64-musl@15.4.0-canary.86':
|
||||||
resolution: {integrity: sha512-7ig1sQHRRgTrj4QHt5l8OT1z2SJnEAHbnEY9SDP2HilwQIfgOAOxveFDBR+f/8AMdAKhCTSeMyrZsivpC0xTUA==}
|
resolution: {integrity: sha512-8MTn6N4Ja25neMLu2Bra1lqW9AWPqsYg0BVs5M/cxL0QkcN3mak/8LLX1vbzz7GigMGSA+NLwg+ol8lglfgIGA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-x64-gnu@15.4.0-canary.3':
|
'@next/swc-linux-x64-gnu@15.4.0-canary.86':
|
||||||
resolution: {integrity: sha512-fML6pzNX9i3DlrCOdE6A1TbVL0aIQkIDDCjrbn/f37hOn88god1OrVd/d4J4w1YqLKQWpmJPnUn6Bkn8qXqbRw==}
|
resolution: {integrity: sha512-hIhzDwWDQHnH0M0Pzaqs1c5fa4+LHiLLEBuPJQvhBxQfH+Eh86DWiWHDCaoNiURvdRPg6uCuF2MjwptrMplEkg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-x64-musl@15.4.0-canary.3':
|
'@next/swc-linux-x64-musl@15.4.0-canary.86':
|
||||||
resolution: {integrity: sha512-87/JPkbr3fgvASdWW2qBVuaXwcjSxgy+CTllj2DgYB7e7BEzT7QJEdj0HJZljBjVbN5oT1FOKwhaVRgRWuwYLQ==}
|
resolution: {integrity: sha512-FG6SBuSeRWYMNu6tsfaZ4iDzv3BLxlpRncO2xvKKQPeUdDSQ0cehuHYnx8fRte8IOAJ3rlbRd6NXvrDarqu92Q==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-win32-arm64-msvc@15.4.0-canary.3':
|
'@next/swc-win32-arm64-msvc@15.4.0-canary.86':
|
||||||
resolution: {integrity: sha512-cTZh72h3ZX8z0lhdVs5m38uyy83mW5r0jz6hKagysPT06uTdOAypK6CRqG5CJSN7RM0n7CkfcO6ExjDqhkDhRA==}
|
resolution: {integrity: sha512-3HvZo4VuyINrNYplRhvC8ILdKwi/vFDHOcTN/I4ru039TFpu2eO6VtXsLBdOdJjGslSSSBYkX+6yRrghihAZDA==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@next/swc-win32-x64-msvc@15.4.0-canary.3':
|
'@next/swc-win32-x64-msvc@15.4.0-canary.86':
|
||||||
resolution: {integrity: sha512-8oZKOKRGad4EVZ94L5Sz2EP59khHIeKGKg+/z8r5mCbBtupLPTXmWjrXoi1R55hHRXJjbW2D5NwcPfJn/ltZ3Q==}
|
resolution: {integrity: sha512-UO9JzGGj7GhtSJFdI0Bl0dkIIBfgbhXLsgNVmq9Z/CsUsQB6J9RS/BMhsxfVwhO+RETk13nFpNutMAhAwcuD8w==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@@ -1824,10 +1815,6 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
esbuild: '>=0.18'
|
esbuild: '>=0.18'
|
||||||
|
|
||||||
busboy@1.6.0:
|
|
||||||
resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==}
|
|
||||||
engines: {node: '>=10.16.0'}
|
|
||||||
|
|
||||||
cac@6.7.14:
|
cac@6.7.14:
|
||||||
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -1856,9 +1843,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
|
resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
caniuse-lite@1.0.30001680:
|
|
||||||
resolution: {integrity: sha512-rPQy70G6AGUMnbwS1z6Xg+RkHYPAi18ihs47GH0jcxIG7wArmPgY3XbS2sRdBbxJljp3thdT8BIqv9ccCypiPA==}
|
|
||||||
|
|
||||||
caniuse-lite@1.0.30001715:
|
caniuse-lite@1.0.30001715:
|
||||||
resolution: {integrity: sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==}
|
resolution: {integrity: sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==}
|
||||||
|
|
||||||
@@ -2159,10 +2143,6 @@ packages:
|
|||||||
engines: {node: '>=0.10'}
|
engines: {node: '>=0.10'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
detect-libc@2.0.3:
|
|
||||||
resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
|
|
||||||
engines: {node: '>=8'}
|
|
||||||
|
|
||||||
detect-libc@2.0.4:
|
detect-libc@2.0.4:
|
||||||
resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
|
resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
@@ -3389,11 +3369,11 @@ packages:
|
|||||||
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
|
resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
next-intl@3.25.1:
|
next-intl@3.26.5:
|
||||||
resolution: {integrity: sha512-Z2dJWn5f/b1sb8EmuJcuDhbQTIp4RG1KBFAILgRt/y27W0ifU7Ll/os3liphUY4InyRH89uShTAk7ItAlpr0uA==}
|
resolution: {integrity: sha512-EQlCIfY0jOhRldiFxwSXG+ImwkQtDEfQeSOEQp6ieAGSLWGlgjdb/Ck/O7wMfC430ZHGeUKVKax8KGusTPKCgg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0
|
next: ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
|
||||||
|
|
||||||
next-themes@0.2.1:
|
next-themes@0.2.1:
|
||||||
resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==}
|
resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==}
|
||||||
@@ -3402,13 +3382,13 @@ packages:
|
|||||||
react: '*'
|
react: '*'
|
||||||
react-dom: '*'
|
react-dom: '*'
|
||||||
|
|
||||||
next@15.4.0-canary.3:
|
next@15.4.0-canary.86:
|
||||||
resolution: {integrity: sha512-OkwxAFNQeuE0vNL7tTwU+jm3nf3x3D5DHSmjRlFktsedGtxZiILZTq6UNExNaFBjttR+2Y6oGqRsFWXC4ob1Wg==}
|
resolution: {integrity: sha512-lGeO0sOvPZ7oFIklqRA863YzRL1bW+kT/OqU3N6RBquHldiucZwnZKQceZdn6WcHEFmWIHzZV+SMG1JEK7hZLg==}
|
||||||
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
|
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@opentelemetry/api': ^1.1.0
|
'@opentelemetry/api': ^1.1.0
|
||||||
'@playwright/test': ^1.41.2
|
'@playwright/test': ^1.51.1
|
||||||
babel-plugin-react-compiler: '*'
|
babel-plugin-react-compiler: '*'
|
||||||
react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
|
react: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
|
||||||
react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
|
react-dom: ^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0
|
||||||
@@ -4170,10 +4150,6 @@ packages:
|
|||||||
stream-combiner@0.0.4:
|
stream-combiner@0.0.4:
|
||||||
resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==}
|
resolution: {integrity: sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==}
|
||||||
|
|
||||||
streamsearch@1.1.0:
|
|
||||||
resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==}
|
|
||||||
engines: {node: '>=10.0.0'}
|
|
||||||
|
|
||||||
string-argv@0.3.2:
|
string-argv@0.3.2:
|
||||||
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
|
resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==}
|
||||||
engines: {node: '>=0.6.19'}
|
engines: {node: '>=0.6.19'}
|
||||||
@@ -4276,11 +4252,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
swr@2.2.5:
|
|
||||||
resolution: {integrity: sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg==}
|
|
||||||
peerDependencies:
|
|
||||||
react: ^16.11.0 || ^17.0.0 || ^18.0.0
|
|
||||||
|
|
||||||
symbol-tree@3.2.4:
|
symbol-tree@3.2.4:
|
||||||
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
|
||||||
|
|
||||||
@@ -4560,15 +4531,10 @@ packages:
|
|||||||
uri-js@4.4.1:
|
uri-js@4.4.1:
|
||||||
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
|
||||||
|
|
||||||
use-intl@3.25.1:
|
use-intl@3.26.5:
|
||||||
resolution: {integrity: sha512-Xeyl0+BjlBf6fJr2h5W/CESZ2IQAH7jzXYK4c/ao+qR26jNPW3FXBLjg7eLRxdeI6QaLcYGLtH3WYhC9I0+6Yg==}
|
resolution: {integrity: sha512-OdsJnC/znPvHCHLQH/duvQNXnP1w0hPfS+tkSi3mAbfjYBGh4JnyfdwkQBfIVf7t8gs9eSX/CntxUMvtKdG2MQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0
|
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0
|
||||||
|
|
||||||
use-sync-external-store@1.2.2:
|
|
||||||
resolution: {integrity: sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==}
|
|
||||||
peerDependencies:
|
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
||||||
|
|
||||||
util-deprecate@1.0.2:
|
util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
@@ -5350,10 +5316,6 @@ snapshots:
|
|||||||
'@formatjs/ecma402-abstract': 2.2.4
|
'@formatjs/ecma402-abstract': 2.2.4
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
|
|
||||||
'@formatjs/intl-localematcher@0.5.4':
|
|
||||||
dependencies:
|
|
||||||
tslib: 2.8.1
|
|
||||||
|
|
||||||
'@formatjs/intl-localematcher@0.5.8':
|
'@formatjs/intl-localematcher@0.5.8':
|
||||||
dependencies:
|
dependencies:
|
||||||
tslib: 2.8.1
|
tslib: 2.8.1
|
||||||
@@ -5538,34 +5500,34 @@ snapshots:
|
|||||||
- encoding
|
- encoding
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@next/env@15.4.0-canary.3': {}
|
'@next/env@15.4.0-canary.86': {}
|
||||||
|
|
||||||
'@next/eslint-plugin-next@14.2.18':
|
'@next/eslint-plugin-next@14.2.18':
|
||||||
dependencies:
|
dependencies:
|
||||||
glob: 10.3.10
|
glob: 10.3.10
|
||||||
|
|
||||||
'@next/swc-darwin-arm64@15.4.0-canary.3':
|
'@next/swc-darwin-arm64@15.4.0-canary.86':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-darwin-x64@15.4.0-canary.3':
|
'@next/swc-darwin-x64@15.4.0-canary.86':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-arm64-gnu@15.4.0-canary.3':
|
'@next/swc-linux-arm64-gnu@15.4.0-canary.86':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-arm64-musl@15.4.0-canary.3':
|
'@next/swc-linux-arm64-musl@15.4.0-canary.86':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-x64-gnu@15.4.0-canary.3':
|
'@next/swc-linux-x64-gnu@15.4.0-canary.86':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-x64-musl@15.4.0-canary.3':
|
'@next/swc-linux-x64-musl@15.4.0-canary.86':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-win32-arm64-msvc@15.4.0-canary.3':
|
'@next/swc-win32-arm64-msvc@15.4.0-canary.86':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-win32-x64-msvc@15.4.0-canary.3':
|
'@next/swc-win32-x64-msvc@15.4.0-canary.86':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1':
|
'@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1':
|
||||||
@@ -6027,11 +5989,11 @@ snapshots:
|
|||||||
|
|
||||||
'@ungap/structured-clone@1.2.0': {}
|
'@ungap/structured-clone@1.2.0': {}
|
||||||
|
|
||||||
'@vercel/analytics@1.3.1(next@15.4.0-canary.3(@babel/core@7.26.10)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react@19.1.0)':
|
'@vercel/analytics@1.3.1(next@15.4.0-canary.86(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react@19.1.0)':
|
||||||
dependencies:
|
dependencies:
|
||||||
server-only: 0.0.1
|
server-only: 0.0.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
next: 15.4.0-canary.3(@babel/core@7.26.10)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0)
|
next: 15.4.0-canary.86(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0)
|
||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
|
|
||||||
'@vercel/git-hooks@1.0.0': {}
|
'@vercel/git-hooks@1.0.0': {}
|
||||||
@@ -6099,7 +6061,7 @@ snapshots:
|
|||||||
|
|
||||||
agent-base@6.0.2:
|
agent-base@6.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.0(supports-color@5.5.0)
|
debug: 4.4.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -6338,10 +6300,6 @@ snapshots:
|
|||||||
esbuild: 0.25.2
|
esbuild: 0.25.2
|
||||||
load-tsconfig: 0.2.5
|
load-tsconfig: 0.2.5
|
||||||
|
|
||||||
busboy@1.6.0:
|
|
||||||
dependencies:
|
|
||||||
streamsearch: 1.1.0
|
|
||||||
|
|
||||||
cac@6.7.14: {}
|
cac@6.7.14: {}
|
||||||
|
|
||||||
cachedir@2.4.0: {}
|
cachedir@2.4.0: {}
|
||||||
@@ -6368,8 +6326,6 @@ snapshots:
|
|||||||
|
|
||||||
camelcase-css@2.0.1: {}
|
camelcase-css@2.0.1: {}
|
||||||
|
|
||||||
caniuse-lite@1.0.30001680: {}
|
|
||||||
|
|
||||||
caniuse-lite@1.0.30001715: {}
|
caniuse-lite@1.0.30001715: {}
|
||||||
|
|
||||||
case-anything@2.1.13: {}
|
case-anything@2.1.13: {}
|
||||||
@@ -6636,6 +6592,10 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
|
|
||||||
|
debug@4.4.0:
|
||||||
|
dependencies:
|
||||||
|
ms: 2.1.3
|
||||||
|
|
||||||
debug@4.4.0(supports-color@5.5.0):
|
debug@4.4.0(supports-color@5.5.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.3
|
ms: 2.1.3
|
||||||
@@ -6713,9 +6673,6 @@ snapshots:
|
|||||||
|
|
||||||
detect-libc@1.0.3: {}
|
detect-libc@1.0.3: {}
|
||||||
|
|
||||||
detect-libc@2.0.3:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
detect-libc@2.0.4: {}
|
detect-libc@2.0.4: {}
|
||||||
|
|
||||||
didyoumean@1.2.2: {}
|
didyoumean@1.2.2: {}
|
||||||
@@ -7321,7 +7278,7 @@ snapshots:
|
|||||||
|
|
||||||
follow-redirects@1.15.9(debug@4.4.0):
|
follow-redirects@1.15.9(debug@4.4.0):
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
debug: 4.4.0(supports-color@5.5.0)
|
debug: 4.4.0
|
||||||
|
|
||||||
for-each@0.3.3:
|
for-each@0.3.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -7581,7 +7538,7 @@ snapshots:
|
|||||||
http-proxy-agent@7.0.2:
|
http-proxy-agent@7.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 7.1.3
|
agent-base: 7.1.3
|
||||||
debug: 4.4.0(supports-color@5.5.0)
|
debug: 4.4.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -7594,14 +7551,14 @@ snapshots:
|
|||||||
https-proxy-agent@5.0.1:
|
https-proxy-agent@5.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 6.0.2
|
agent-base: 6.0.2
|
||||||
debug: 4.4.0(supports-color@5.5.0)
|
debug: 4.4.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
https-proxy-agent@7.0.6:
|
https-proxy-agent@7.0.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
agent-base: 7.1.3
|
agent-base: 7.1.3
|
||||||
debug: 4.4.0(supports-color@5.5.0)
|
debug: 4.4.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -7950,7 +7907,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
chalk: 5.4.1
|
chalk: 5.4.1
|
||||||
commander: 13.1.0
|
commander: 13.1.0
|
||||||
debug: 4.4.0(supports-color@5.5.0)
|
debug: 4.4.0
|
||||||
execa: 8.0.1
|
execa: 8.0.1
|
||||||
lilconfig: 3.1.3
|
lilconfig: 3.1.3
|
||||||
listr2: 8.3.2
|
listr2: 8.3.2
|
||||||
@@ -8134,40 +8091,38 @@ snapshots:
|
|||||||
|
|
||||||
negotiator@1.0.0: {}
|
negotiator@1.0.0: {}
|
||||||
|
|
||||||
next-intl@3.25.1(next@15.4.0-canary.3(@babel/core@7.26.10)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react@19.1.0):
|
next-intl@3.26.5(next@15.4.0-canary.86(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/intl-localematcher': 0.5.4
|
'@formatjs/intl-localematcher': 0.5.8
|
||||||
negotiator: 1.0.0
|
negotiator: 1.0.0
|
||||||
next: 15.4.0-canary.3(@babel/core@7.26.10)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0)
|
next: 15.4.0-canary.86(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0)
|
||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
use-intl: 3.25.1(react@19.1.0)
|
use-intl: 3.26.5(react@19.1.0)
|
||||||
|
|
||||||
next-themes@0.2.1(next@15.4.0-canary.3(@babel/core@7.26.10)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
|
next-themes@0.2.1(next@15.4.0-canary.86(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
next: 15.4.0-canary.3(@babel/core@7.26.10)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0)
|
next: 15.4.0-canary.86(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0)
|
||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
react-dom: 19.1.0(react@19.1.0)
|
react-dom: 19.1.0(react@19.1.0)
|
||||||
|
|
||||||
next@15.4.0-canary.3(@babel/core@7.26.10)(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0):
|
next@15.4.0-canary.86(@playwright/test@1.52.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(sass@1.87.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@next/env': 15.4.0-canary.3
|
'@next/env': 15.4.0-canary.86
|
||||||
'@swc/counter': 0.1.3
|
|
||||||
'@swc/helpers': 0.5.15
|
'@swc/helpers': 0.5.15
|
||||||
busboy: 1.6.0
|
caniuse-lite: 1.0.30001715
|
||||||
caniuse-lite: 1.0.30001680
|
|
||||||
postcss: 8.4.31
|
postcss: 8.4.31
|
||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
react-dom: 19.1.0(react@19.1.0)
|
react-dom: 19.1.0(react@19.1.0)
|
||||||
styled-jsx: 5.1.6(@babel/core@7.26.10)(react@19.1.0)
|
styled-jsx: 5.1.6(react@19.1.0)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@next/swc-darwin-arm64': 15.4.0-canary.3
|
'@next/swc-darwin-arm64': 15.4.0-canary.86
|
||||||
'@next/swc-darwin-x64': 15.4.0-canary.3
|
'@next/swc-darwin-x64': 15.4.0-canary.86
|
||||||
'@next/swc-linux-arm64-gnu': 15.4.0-canary.3
|
'@next/swc-linux-arm64-gnu': 15.4.0-canary.86
|
||||||
'@next/swc-linux-arm64-musl': 15.4.0-canary.3
|
'@next/swc-linux-arm64-musl': 15.4.0-canary.86
|
||||||
'@next/swc-linux-x64-gnu': 15.4.0-canary.3
|
'@next/swc-linux-x64-gnu': 15.4.0-canary.86
|
||||||
'@next/swc-linux-x64-musl': 15.4.0-canary.3
|
'@next/swc-linux-x64-musl': 15.4.0-canary.86
|
||||||
'@next/swc-win32-arm64-msvc': 15.4.0-canary.3
|
'@next/swc-win32-arm64-msvc': 15.4.0-canary.86
|
||||||
'@next/swc-win32-x64-msvc': 15.4.0-canary.3
|
'@next/swc-win32-x64-msvc': 15.4.0-canary.86
|
||||||
'@playwright/test': 1.52.0
|
'@playwright/test': 1.52.0
|
||||||
sass: 1.87.0
|
sass: 1.87.0
|
||||||
sharp: 0.34.1
|
sharp: 0.34.1
|
||||||
@@ -8737,7 +8692,7 @@ snapshots:
|
|||||||
sharp@0.34.1:
|
sharp@0.34.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
color: 4.2.3
|
color: 4.2.3
|
||||||
detect-libc: 2.0.3
|
detect-libc: 2.0.4
|
||||||
semver: 7.7.1
|
semver: 7.7.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@img/sharp-darwin-arm64': 0.34.1
|
'@img/sharp-darwin-arm64': 0.34.1
|
||||||
@@ -8882,7 +8837,7 @@ snapshots:
|
|||||||
arg: 5.0.2
|
arg: 5.0.2
|
||||||
bluebird: 3.7.2
|
bluebird: 3.7.2
|
||||||
check-more-types: 2.24.0
|
check-more-types: 2.24.0
|
||||||
debug: 4.4.0(supports-color@5.5.0)
|
debug: 4.4.0
|
||||||
execa: 5.1.1
|
execa: 5.1.1
|
||||||
lazy-ass: 1.6.0
|
lazy-ass: 1.6.0
|
||||||
ps-tree: 1.2.0
|
ps-tree: 1.2.0
|
||||||
@@ -8900,8 +8855,6 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
duplexer: 0.1.2
|
duplexer: 0.1.2
|
||||||
|
|
||||||
streamsearch@1.1.0: {}
|
|
||||||
|
|
||||||
string-argv@0.3.2: {}
|
string-argv@0.3.2: {}
|
||||||
|
|
||||||
string-width@4.2.3:
|
string-width@4.2.3:
|
||||||
@@ -8990,12 +8943,10 @@ snapshots:
|
|||||||
|
|
||||||
strip-json-comments@3.1.1: {}
|
strip-json-comments@3.1.1: {}
|
||||||
|
|
||||||
styled-jsx@5.1.6(@babel/core@7.26.10)(react@19.1.0):
|
styled-jsx@5.1.6(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
client-only: 0.0.1
|
client-only: 0.0.1
|
||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
optionalDependencies:
|
|
||||||
'@babel/core': 7.26.10
|
|
||||||
|
|
||||||
sucrase@3.35.0:
|
sucrase@3.35.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9021,12 +8972,6 @@ snapshots:
|
|||||||
|
|
||||||
supports-preserve-symlinks-flag@1.0.0: {}
|
supports-preserve-symlinks-flag@1.0.0: {}
|
||||||
|
|
||||||
swr@2.2.5(react@19.1.0):
|
|
||||||
dependencies:
|
|
||||||
client-only: 0.0.1
|
|
||||||
react: 19.1.0
|
|
||||||
use-sync-external-store: 1.2.2(react@19.1.0)
|
|
||||||
|
|
||||||
symbol-tree@3.2.4: {}
|
symbol-tree@3.2.4: {}
|
||||||
|
|
||||||
tabbable@6.2.0: {}
|
tabbable@6.2.0: {}
|
||||||
@@ -9309,16 +9254,12 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
punycode: 2.3.1
|
punycode: 2.3.1
|
||||||
|
|
||||||
use-intl@3.25.1(react@19.1.0):
|
use-intl@3.26.5(react@19.1.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@formatjs/fast-memoize': 2.2.3
|
'@formatjs/fast-memoize': 2.2.3
|
||||||
intl-messageformat: 10.7.7
|
intl-messageformat: 10.7.7
|
||||||
react: 19.1.0
|
react: 19.1.0
|
||||||
|
|
||||||
use-sync-external-store@1.2.2(react@19.1.0):
|
|
||||||
dependencies:
|
|
||||||
react: 19.1.0
|
|
||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|
||||||
uuid@11.1.0: {}
|
uuid@11.1.0: {}
|
||||||
|
Reference in New Issue
Block a user