mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-26 09:12:16 +00:00
fix(login): respect password complexity settings in UI (#11528)
<!-- Please inform yourself about the contribution guidelines on submitting a PR here: https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md#submit-a-pull-request-pr. Take note of how PR/commit titles should be written and replace the template texts in the sections below. Don't remove any of the sections. It is important that the commit history clearly shows what is changed and why. Important: By submitting a contribution you agree to the terms from our Licensing Policy as described here: https://github.com/zitadel/zitadel/blob/main/LICENSING.md#community-contributions. --> # Which Problems Are Solved - Login V2 UI displays all password complexity requirements (symbol, number, uppercase, lowercase) regardless of the actual instance/organization configuration - Users see requirements they don't need to meet, causing confusion # How the Problems Are Solved - Updated the PasswordComplexity component to conditionally render each requirement based on the corresponding `requires*` flag from the password complexity settings - Only enabled requirements are now displayed to users # Additional Changes None. # Additional Context - Closes #11511
This commit is contained in:
@@ -119,7 +119,7 @@ describe("<PasswordComplexity/>", () => {
|
||||
expect(svg).toHaveClass("text-warn-light-500");
|
||||
});
|
||||
|
||||
test("should render all complexity checks", () => {
|
||||
test("should render all complexity checks when all requirements are enabled", () => {
|
||||
render(
|
||||
<NextIntlClientProvider locale="en" messages={messages}>
|
||||
<PasswordComplexity
|
||||
@@ -144,5 +144,138 @@ describe("<PasswordComplexity/>", () => {
|
||||
expect(screen.getByTestId("number-check")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("uppercase-check")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("lowercase-check")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("equal-check")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("should not render symbol check when requiresSymbol is false", () => {
|
||||
render(
|
||||
<NextIntlClientProvider locale="en" messages={messages}>
|
||||
<PasswordComplexity
|
||||
password="Password1!"
|
||||
equals
|
||||
passwordComplexitySettings={
|
||||
{
|
||||
minLength: BigInt(8),
|
||||
requiresLowercase: true,
|
||||
requiresUppercase: true,
|
||||
requiresNumber: true,
|
||||
requiresSymbol: false,
|
||||
resourceOwnerType: 0,
|
||||
} as any
|
||||
}
|
||||
/>
|
||||
</NextIntlClientProvider>,
|
||||
);
|
||||
|
||||
expect(screen.queryByTestId("symbol-check")).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId("number-check")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("uppercase-check")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("lowercase-check")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("should not render number check when requiresNumber is false", () => {
|
||||
render(
|
||||
<NextIntlClientProvider locale="en" messages={messages}>
|
||||
<PasswordComplexity
|
||||
password="Password1!"
|
||||
equals
|
||||
passwordComplexitySettings={
|
||||
{
|
||||
minLength: BigInt(8),
|
||||
requiresLowercase: true,
|
||||
requiresUppercase: true,
|
||||
requiresNumber: false,
|
||||
requiresSymbol: true,
|
||||
resourceOwnerType: 0,
|
||||
} as any
|
||||
}
|
||||
/>
|
||||
</NextIntlClientProvider>,
|
||||
);
|
||||
|
||||
expect(screen.getByTestId("symbol-check")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("number-check")).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId("uppercase-check")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("lowercase-check")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("should not render uppercase check when requiresUppercase is false", () => {
|
||||
render(
|
||||
<NextIntlClientProvider locale="en" messages={messages}>
|
||||
<PasswordComplexity
|
||||
password="Password1!"
|
||||
equals
|
||||
passwordComplexitySettings={
|
||||
{
|
||||
minLength: BigInt(8),
|
||||
requiresLowercase: true,
|
||||
requiresUppercase: false,
|
||||
requiresNumber: true,
|
||||
requiresSymbol: true,
|
||||
resourceOwnerType: 0,
|
||||
} as any
|
||||
}
|
||||
/>
|
||||
</NextIntlClientProvider>,
|
||||
);
|
||||
|
||||
expect(screen.getByTestId("symbol-check")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("number-check")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("uppercase-check")).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId("lowercase-check")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("should not render lowercase check when requiresLowercase is false", () => {
|
||||
render(
|
||||
<NextIntlClientProvider locale="en" messages={messages}>
|
||||
<PasswordComplexity
|
||||
password="Password1!"
|
||||
equals
|
||||
passwordComplexitySettings={
|
||||
{
|
||||
minLength: BigInt(8),
|
||||
requiresLowercase: false,
|
||||
requiresUppercase: true,
|
||||
requiresNumber: true,
|
||||
requiresSymbol: true,
|
||||
resourceOwnerType: 0,
|
||||
} as any
|
||||
}
|
||||
/>
|
||||
</NextIntlClientProvider>,
|
||||
);
|
||||
|
||||
expect(screen.getByTestId("symbol-check")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("number-check")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("uppercase-check")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("lowercase-check")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
test("should only render length and equals checks when all other requirements are disabled", () => {
|
||||
render(
|
||||
<NextIntlClientProvider locale="en" messages={messages}>
|
||||
<PasswordComplexity
|
||||
password="password"
|
||||
equals
|
||||
passwordComplexitySettings={
|
||||
{
|
||||
minLength: BigInt(8),
|
||||
requiresLowercase: false,
|
||||
requiresUppercase: false,
|
||||
requiresNumber: false,
|
||||
requiresSymbol: false,
|
||||
resourceOwnerType: 0,
|
||||
} as any
|
||||
}
|
||||
/>
|
||||
</NextIntlClientProvider>,
|
||||
);
|
||||
|
||||
expect(screen.getByTestId("length-check")).toBeInTheDocument();
|
||||
expect(screen.getByTestId("equal-check")).toBeInTheDocument();
|
||||
expect(screen.queryByTestId("symbol-check")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId("number-check")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId("uppercase-check")).not.toBeInTheDocument();
|
||||
expect(screen.queryByTestId("lowercase-check")).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -91,33 +91,39 @@ export function PasswordComplexity({
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<span />
|
||||
) : null}
|
||||
{passwordComplexitySettings.requiresSymbol && (
|
||||
<div className="flex flex-row items-center" data-testid="symbol-check">
|
||||
{renderIcon(hasSymbol, t)}
|
||||
<span className={desc}>
|
||||
<Translated i18nKey="complexity.hasSymbol" namespace="password" />
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{passwordComplexitySettings.requiresNumber && (
|
||||
<div className="flex flex-row items-center" data-testid="number-check">
|
||||
{renderIcon(hasNumber, t)}
|
||||
<span className={desc}>
|
||||
<Translated i18nKey="complexity.hasNumber" namespace="password" />
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{passwordComplexitySettings.requiresUppercase && (
|
||||
<div className="flex flex-row items-center" data-testid="uppercase-check">
|
||||
{renderIcon(hasUppercase, t)}
|
||||
<span className={desc}>
|
||||
<Translated i18nKey="complexity.hasUppercase" namespace="password" />
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{passwordComplexitySettings.requiresLowercase && (
|
||||
<div className="flex flex-row items-center" data-testid="lowercase-check">
|
||||
{renderIcon(hasLowercase, t)}
|
||||
<span className={desc}>
|
||||
<Translated i18nKey="complexity.hasLowercase" namespace="password" />
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-row items-center" data-testid="symbol-check">
|
||||
{renderIcon(hasSymbol, t)}
|
||||
<span className={desc}>
|
||||
<Translated i18nKey="complexity.hasSymbol" namespace="password" />
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-row items-center" data-testid="number-check">
|
||||
{renderIcon(hasNumber, t)}
|
||||
<span className={desc}>
|
||||
<Translated i18nKey="complexity.hasNumber" namespace="password" />
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-row items-center" data-testid="uppercase-check">
|
||||
{renderIcon(hasUppercase, t)}
|
||||
<span className={desc}>
|
||||
<Translated i18nKey="complexity.hasUppercase" namespace="password" />
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-row items-center" data-testid="lowercase-check">
|
||||
{renderIcon(hasLowercase, t)}
|
||||
<span className={desc}>
|
||||
<Translated i18nKey="complexity.hasLowercase" namespace="password" />
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-row items-center" data-testid="equal-check">
|
||||
{renderIcon(equals, t)}
|
||||
<span className={desc}>
|
||||
|
||||
Reference in New Issue
Block a user