change search user

This commit is contained in:
Max Peintner
2025-01-09 09:38:29 +01:00
parent dd3e501817
commit 3809b8dc93
4 changed files with 140 additions and 14 deletions

View File

@@ -54,6 +54,7 @@ export default async function Page(props: {
loginName={loginName}
authRequestId={authRequestId}
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
loginSettings={loginSettings}
submit={submit}
allowRegister={!!loginSettings?.allowRegister}
>

View File

@@ -1,6 +1,7 @@
"use client";
import { sendLoginname } from "@/lib/server/loginname";
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { useTranslations } from "next-intl";
import { useRouter } from "next/navigation";
import { ReactNode, useEffect, useState } from "react";
@@ -18,6 +19,7 @@ type Inputs = {
type Props = {
loginName: string | undefined;
authRequestId: string | undefined;
loginSettings: LoginSettings | undefined;
organization?: string;
submit: boolean;
allowRegister: boolean;
@@ -28,6 +30,7 @@ export function UsernameForm({
loginName,
authRequestId,
organization,
loginSettings,
submit,
allowRegister,
children,
@@ -80,6 +83,18 @@ export function UsernameForm({
}
}, []);
let inputLabel = "Loginname";
if (
loginSettings?.disableLoginWithEmail &&
loginSettings?.disableLoginWithPhone
) {
inputLabel = "Username";
} else if (loginSettings?.disableLoginWithEmail) {
inputLabel = "Username or phone number";
} else if (loginSettings?.disableLoginWithPhone) {
inputLabel = "Username or email";
}
return (
<form className="w-full">
<div className="">
@@ -87,7 +102,7 @@ export function UsernameForm({
type="text"
autoComplete="username"
{...register("loginName", { required: "This field is required" })}
label="Loginname"
label={inputLabel}
data-testid="username-text-input"
/>
{allowRegister && (

View File

@@ -16,8 +16,8 @@ import {
getOrgsByDomain,
listAuthenticationMethodTypes,
listIDPLinks,
listUsers,
ListUsersCommand,
searchUsers,
SearchUsersCommand,
startIdentityProviderFlow,
} from "../zitadel";
import { createSessionAndUpdateCookie } from "./cookie";
@@ -33,20 +33,17 @@ const ORG_SUFFIX_REGEX = /(?<=@)(.+)/;
export async function sendLoginname(command: SendLoginnameCommand) {
const loginSettingsByContext = await getLoginSettings(command.organization);
let listUsersRequest: ListUsersCommand = {
userName: command.loginName,
if (!loginSettingsByContext) {
return { error: "Could not get login settings" };
}
let searchUsersRequest: SearchUsersCommand = {
searchValue: command.loginName,
organizationId: command.organization,
loginSettings: loginSettingsByContext,
};
if (!loginSettingsByContext?.disableLoginWithEmail) {
listUsersRequest.email = command.loginName;
}
if (!loginSettingsByContext?.disableLoginWithPhone) {
listUsersRequest.phone = command.loginName;
}
const { result: potentialUsers } = await listUsers(listUsersRequest);
const { result: potentialUsers } = await searchUsers(searchUsersRequest);
const redirectUserToSingleIDPIfAvailable = async () => {
const identityProviders = await getActiveIdentityProviders(

View File

@@ -26,6 +26,7 @@ import { create, Duration } from "@zitadel/client";
import { TextQueryMethod } from "@zitadel/proto/zitadel/object/v2/object_pb";
import { CreateCallbackRequest } from "@zitadel/proto/zitadel/oidc/v2/oidc_service_pb";
import { Organization } from "@zitadel/proto/zitadel/org/v2/org_pb";
import { LoginSettings } from "@zitadel/proto/zitadel/settings/v2/login_settings_pb";
import { SendEmailVerificationCodeSchema } from "@zitadel/proto/zitadel/user/v2/email_pb";
import type { RedirectURLsJson } from "@zitadel/proto/zitadel/user/v2/idp_pb";
import {
@@ -408,6 +409,118 @@ export async function listUsers({
);
}
if (organizationId) {
queries.push(
create(SearchQuerySchema, {
query: {
case: "organizationIdQuery",
value: {
organizationId,
},
},
}),
);
}
console.log(queries);
return userService.listUsers({ queries: queries });
}
export type SearchUsersCommand = {
searchValue: string;
loginSettings: LoginSettings;
organizationId?: string;
};
const PhoneQuery = (searchValue: string) =>
create(SearchQuerySchema, {
query: {
case: "phoneQuery",
value: {
number: searchValue,
method: TextQueryMethod.EQUALS,
},
},
});
const UserNameQuery = (searchValue: string) =>
create(SearchQuerySchema, {
query: {
case: "userNameQuery",
value: {
userName: searchValue,
method: TextQueryMethod.EQUALS,
},
},
});
const EmailQuery = (searchValue: string) =>
create(SearchQuerySchema, {
query: {
case: "emailQuery",
value: {
emailAddress: searchValue,
method: TextQueryMethod.EQUALS,
},
},
});
export async function searchUsers({
searchValue,
loginSettings,
organizationId,
}: SearchUsersCommand) {
console.log(loginSettings);
const queries: SearchQuery[] = [];
const orQueries: SearchQuery[] = [];
// either use loginName or userName, email, phone
if (
loginSettings.disableLoginWithEmail &&
loginSettings.disableLoginWithPhone
) {
const userNameQuery = UserNameQuery(searchValue);
queries.push(userNameQuery);
} else if (loginSettings.disableLoginWithEmail) {
const userNameQuery = UserNameQuery(searchValue);
orQueries.push(userNameQuery);
if (searchValue.length <= 20) {
const phoneQuery = PhoneQuery(searchValue);
orQueries.push(phoneQuery);
}
} else if (loginSettings.disableLoginWithPhone) {
const userNameQuery = UserNameQuery(searchValue);
orQueries.push(userNameQuery);
const emailQuery = EmailQuery(searchValue);
orQueries.push(emailQuery);
} else {
const userNameQuery = UserNameQuery(searchValue);
orQueries.push(userNameQuery);
const emailQuery = EmailQuery(searchValue);
orQueries.push(emailQuery);
if (searchValue.length <= 20) {
const phoneQuery = PhoneQuery(searchValue);
orQueries.push(phoneQuery);
}
}
if (orQueries.length > 0) {
queries.push(
create(SearchQuerySchema, {
query: {
case: "orQuery",
value: {
queries: orQueries,
},
},
}),
);
}
if (organizationId) {
queries.push(
create(SearchQuerySchema, {