2024-09-26 22:50:55 -04:00
import { Alert } from "@/components/alert" ;
import { DynamicTheme } from "@/components/dynamic-theme" ;
import { PasswordForm } from "@/components/password-form" ;
import { UserAvatar } from "@/components/user-avatar" ;
2025-01-28 09:47:35 +01:00
import { getApiUrlOfHeaders } from "@/lib/service" ;
2024-09-04 15:47:29 +02:00
import { loadMostRecentSession } from "@/lib/session" ;
2024-11-12 15:30:57 +01:00
import {
getBrandingSettings ,
getDefaultOrg ,
getLoginSettings ,
} from "@/lib/zitadel" ;
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb" ;
2024-09-16 11:36:44 +02:00
import { PasskeysType } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb" ;
2024-10-09 14:03:01 +02:00
import { getLocale , getTranslations } from "next-intl/server" ;
2025-01-15 09:57:24 +01:00
import { headers } from "next/headers" ;
2023-04-03 13:39:51 +02:00
2024-11-22 11:27:37 +01:00
export default async function Page ( props : {
searchParams : Promise < Record < string | number | symbol , string | undefined > > ;
} ) {
2024-11-22 11:25:03 +01:00
const searchParams = await props . searchParams ;
2024-10-09 14:03:01 +02:00
const locale = getLocale ( ) ;
const t = await getTranslations ( { locale , namespace : "password" } ) ;
2024-10-17 16:35:30 +02:00
const tError = await getTranslations ( { locale , namespace : "error" } ) ;
2024-10-09 14:03:01 +02:00
2024-11-12 15:30:57 +01:00
let { loginName , organization , authRequestId , alt } = searchParams ;
2025-01-28 09:47:35 +01:00
const _headers = await headers ( ) ;
2025-01-29 10:34:33 +01:00
const serviceUrl = getApiUrlOfHeaders ( _headers ) ;
2025-01-15 09:57:24 +01:00
2024-11-12 15:30:57 +01:00
let defaultOrganization ;
if ( ! organization ) {
2025-01-29 10:34:33 +01:00
const org : Organization | null = await getDefaultOrg ( { serviceUrl } ) ;
2024-11-14 10:35:36 +01:00
2024-11-12 16:54:42 +01:00
if ( org ) {
2024-11-12 15:30:57 +01:00
defaultOrganization = org . id ;
}
}
2023-04-03 13:39:51 +02:00
2024-09-18 14:13:04 +02:00
// also allow no session to be found (ignoreUnkownUsername)
let sessionFactors ;
try {
sessionFactors = await loadMostRecentSession ( {
2025-01-29 10:34:33 +01:00
serviceUrl ,
2025-01-15 09:57:24 +01:00
sessionParams : {
loginName ,
organization ,
} ,
2024-09-18 14:13:04 +02:00
} ) ;
} catch ( error ) {
// ignore error to continue to show the password form
console . warn ( error ) ;
}
2023-05-22 16:28:47 +02:00
2025-01-15 09:57:24 +01:00
const branding = await getBrandingSettings ( {
2025-01-29 10:34:33 +01:00
serviceUrl ,
2025-01-15 09:57:24 +01:00
organization : organization ? ? defaultOrganization ,
} ) ;
const loginSettings = await getLoginSettings ( {
2025-01-29 10:34:33 +01:00
serviceUrl ,
2025-01-15 09:57:24 +01:00
organization : organization ? ? defaultOrganization ,
} ) ;
2024-04-01 10:00:31 +02:00
2023-04-03 13:39:51 +02:00
return (
2024-04-01 10:00:31 +02:00
< DynamicTheme branding = { branding } >
< div className = "flex flex-col items-center space-y-4" >
2024-10-16 16:29:48 +02:00
< h1 >
{ sessionFactors ? . factors ? . user ? . displayName ? ? t ( "verify.title" ) }
< / h1 >
< p className = "ztdl-p mb-6 block" > { t ( "verify.description" ) } < / p >
2024-04-01 10:00:31 +02:00
2024-09-18 14:13:04 +02:00
{ /* show error only if usernames should be shown to be unknown */ }
{ ( ! sessionFactors || ! loginName ) &&
! loginSettings ? . ignoreUnknownUsernames && (
< div className = "py-4" >
2024-10-17 16:35:30 +02:00
< Alert > { tError ( "unknownContext" ) } < / Alert >
2024-09-18 14:13:04 +02:00
< / div >
) }
2024-04-01 10:00:31 +02:00
{ sessionFactors && (
< UserAvatar
loginName = { loginName ? ? sessionFactors . factors ? . user ? . loginName }
displayName = { sessionFactors . factors ? . user ? . displayName }
showDropdown
2024-05-03 10:09:18 +02:00
searchParams = { searchParams }
2024-04-01 10:00:31 +02:00
> < / UserAvatar >
) }
2024-09-03 14:15:42 +02:00
{ loginName && (
< PasswordForm
loginName = { loginName }
authRequestId = { authRequestId }
2024-11-12 15:30:57 +01:00
organization = { organization } // stick to "organization" as we still want to do user discovery based on the searchParams not the default organization, later the organization is determined by the found user
2024-09-03 14:15:42 +02:00
loginSettings = { loginSettings }
2024-09-16 11:36:44 +02:00
promptPasswordless = {
2024-11-22 09:54:08 +01:00
loginSettings ? . passkeysType == PasskeysType . ALLOWED
2024-09-16 11:36:44 +02:00
}
2024-09-03 14:15:42 +02:00
isAlternative = { alt === "true" }
/ >
) }
2024-04-01 10:00:31 +02:00
< / div >
< / DynamicTheme >
2023-04-03 13:39:51 +02:00
) ;
}