fix: Check password strength on password auto-fill (#2148)
Fixes password strength not being checked when new passwords are auto-filled, resulting in submit buttons remaining disabled. --------- Co-authored-by: SuaYoo <SuaYoo@users.noreply.github.com> Co-authored-by: emma <hi@emma.cafe>
This commit is contained in:
parent
2f3dff3de5
commit
333ab6d9e9
@ -1,7 +1,7 @@
|
|||||||
import { localized, msg, str } from "@lit/localize";
|
import { localized, msg, str } from "@lit/localize";
|
||||||
import type { SlInput } from "@shoelace-style/shoelace";
|
import type { SlInput } from "@shoelace-style/shoelace";
|
||||||
import type { ZxcvbnResult } from "@zxcvbn-ts/core";
|
import type { ZxcvbnResult } from "@zxcvbn-ts/core";
|
||||||
import { customElement, property, state } from "lit/decorators.js";
|
import { customElement, property, query, state } from "lit/decorators.js";
|
||||||
import { when } from "lit/directives/when.js";
|
import { when } from "lit/directives/when.js";
|
||||||
import debounce from "lodash/fp/debounce";
|
import debounce from "lodash/fp/debounce";
|
||||||
|
|
||||||
@ -54,6 +54,9 @@ export class SignUpForm extends LiteElement {
|
|||||||
@state()
|
@state()
|
||||||
private showLoginLink = false;
|
private showLoginLink = false;
|
||||||
|
|
||||||
|
@query('sl-input[name="password"]')
|
||||||
|
private readonly password?: SlInput | null;
|
||||||
|
|
||||||
protected firstUpdated() {
|
protected firstUpdated() {
|
||||||
void PasswordService.setOptions();
|
void PasswordService.setOptions();
|
||||||
}
|
}
|
||||||
@ -121,7 +124,7 @@ export class SignUpForm extends LiteElement {
|
|||||||
passwordToggle
|
passwordToggle
|
||||||
class="hide-required-content"
|
class="hide-required-content"
|
||||||
required
|
required
|
||||||
@input=${this.onPasswordInput as UnderlyingFunction<
|
@sl-input=${this.onPasswordInput as UnderlyingFunction<
|
||||||
typeof this.onPasswordInput
|
typeof this.onPasswordInput
|
||||||
>}
|
>}
|
||||||
>
|
>
|
||||||
@ -174,8 +177,8 @@ export class SignUpForm extends LiteElement {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
private readonly onPasswordInput = debounce(150)(async (e: InputEvent) => {
|
private readonly onPasswordInput = debounce(150)(async () => {
|
||||||
const { value } = e.target as SlInput;
|
const value = this.password?.value;
|
||||||
if (!value || value.length < 4) {
|
if (!value || value.length < 4) {
|
||||||
this.pwStrengthResults = null;
|
this.pwStrengthResults = null;
|
||||||
return;
|
return;
|
||||||
|
@ -3,7 +3,7 @@ import type { SlInput, SlSelectEvent } from "@shoelace-style/shoelace";
|
|||||||
import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js";
|
import { serialize } from "@shoelace-style/shoelace/dist/utilities/form.js";
|
||||||
import type { ZxcvbnResult } from "@zxcvbn-ts/core";
|
import type { ZxcvbnResult } from "@zxcvbn-ts/core";
|
||||||
import { nothing, type PropertyValues } from "lit";
|
import { nothing, type PropertyValues } from "lit";
|
||||||
import { customElement, property, queryAsync, state } from "lit/decorators.js";
|
import { customElement, property, query, state } from "lit/decorators.js";
|
||||||
import { choose } from "lit/directives/choose.js";
|
import { choose } from "lit/directives/choose.js";
|
||||||
import { when } from "lit/directives/when.js";
|
import { when } from "lit/directives/when.js";
|
||||||
import debounce from "lodash/fp/debounce";
|
import debounce from "lodash/fp/debounce";
|
||||||
@ -112,8 +112,8 @@ export class AccountSettings extends LiteElement {
|
|||||||
@state()
|
@state()
|
||||||
private pwStrengthResults: null | ZxcvbnResult = null;
|
private pwStrengthResults: null | ZxcvbnResult = null;
|
||||||
|
|
||||||
@queryAsync('sl-input[name="password"]')
|
@query('sl-input[name="newPassword"]')
|
||||||
private readonly passwordInput?: Promise<SlInput | null>;
|
private readonly newPassword?: SlInput | null;
|
||||||
|
|
||||||
private get activeTab() {
|
private get activeTab() {
|
||||||
return this.tab && Object.values(Tab).includes(this.tab as unknown as Tab)
|
return this.tab && Object.values(Tab).includes(this.tab as unknown as Tab)
|
||||||
@ -257,7 +257,7 @@ export class AccountSettings extends LiteElement {
|
|||||||
name="password"
|
name="password"
|
||||||
label=${msg("Enter your current password")}
|
label=${msg("Enter your current password")}
|
||||||
type="password"
|
type="password"
|
||||||
autocomplete="off"
|
autocomplete="current-password"
|
||||||
password-toggle
|
password-toggle
|
||||||
required
|
required
|
||||||
></sl-input>
|
></sl-input>
|
||||||
@ -269,7 +269,7 @@ export class AccountSettings extends LiteElement {
|
|||||||
password-toggle
|
password-toggle
|
||||||
minlength="8"
|
minlength="8"
|
||||||
required
|
required
|
||||||
@input=${this.onPasswordInput as UnderlyingFunction<
|
@sl-input=${this.onPasswordInput as UnderlyingFunction<
|
||||||
typeof this.onPasswordInput
|
typeof this.onPasswordInput
|
||||||
>}
|
>}
|
||||||
></sl-input>
|
></sl-input>
|
||||||
@ -375,8 +375,8 @@ export class AccountSettings extends LiteElement {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
private readonly onPasswordInput = debounce(150)(async (e: InputEvent) => {
|
private readonly onPasswordInput = debounce(150)(async () => {
|
||||||
const { value } = e.target as SlInput;
|
const value = this.newPassword?.value;
|
||||||
if (!value || value.length < 4) {
|
if (!value || value.length < 4) {
|
||||||
this.pwStrengthResults = null;
|
this.pwStrengthResults = null;
|
||||||
return;
|
return;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { localized, msg, str } from "@lit/localize";
|
import { localized, msg, str } from "@lit/localize";
|
||||||
import type { SlInput } from "@shoelace-style/shoelace";
|
import type { SlInput } from "@shoelace-style/shoelace";
|
||||||
import type { ZxcvbnResult } from "@zxcvbn-ts/core";
|
import type { ZxcvbnResult } from "@zxcvbn-ts/core";
|
||||||
import { customElement, property, state } from "lit/decorators.js";
|
import { customElement, property, query, state } from "lit/decorators.js";
|
||||||
import { when } from "lit/directives/when.js";
|
import { when } from "lit/directives/when.js";
|
||||||
import debounce from "lodash/fp/debounce";
|
import debounce from "lodash/fp/debounce";
|
||||||
|
|
||||||
@ -28,6 +28,9 @@ export class ResetPassword extends LiteElement {
|
|||||||
@state()
|
@state()
|
||||||
private isSubmitting = false;
|
private isSubmitting = false;
|
||||||
|
|
||||||
|
@query('sl-input[name="newPassword"]')
|
||||||
|
private readonly newPassword?: SlInput | null;
|
||||||
|
|
||||||
protected firstUpdated() {
|
protected firstUpdated() {
|
||||||
void PasswordService.setOptions();
|
void PasswordService.setOptions();
|
||||||
}
|
}
|
||||||
@ -52,16 +55,15 @@ export class ResetPassword extends LiteElement {
|
|||||||
<div class="mb-5">
|
<div class="mb-5">
|
||||||
<sl-input
|
<sl-input
|
||||||
id="password"
|
id="password"
|
||||||
name="password"
|
name="newPassword"
|
||||||
type="password"
|
type="password"
|
||||||
label="${msg("Enter new password")}"
|
label="${msg("Enter new password")}"
|
||||||
help-text=${msg("Must be between 8-64 characters")}
|
|
||||||
minlength="8"
|
minlength="8"
|
||||||
autocomplete="new-password"
|
autocomplete="new-password"
|
||||||
passwordToggle
|
passwordToggle
|
||||||
class="hide-required-content"
|
class="hide-required-content"
|
||||||
required
|
required
|
||||||
@input=${this.onPasswordInput as UnderlyingFunction<
|
@sl-input=${this.onPasswordInput as UnderlyingFunction<
|
||||||
typeof this.onPasswordInput
|
typeof this.onPasswordInput
|
||||||
>}
|
>}
|
||||||
>
|
>
|
||||||
@ -110,8 +112,8 @@ export class ResetPassword extends LiteElement {
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
private readonly onPasswordInput = debounce(150)(async (e: InputEvent) => {
|
private readonly onPasswordInput = debounce(150)(async () => {
|
||||||
const { value } = e.target as SlInput;
|
const value = this.newPassword?.value;
|
||||||
if (!value || value.length < 4) {
|
if (!value || value.length < 4) {
|
||||||
this.pwStrengthResults = null;
|
this.pwStrengthResults = null;
|
||||||
return;
|
return;
|
||||||
@ -124,7 +126,7 @@ export class ResetPassword extends LiteElement {
|
|||||||
this.isSubmitting = true;
|
this.isSubmitting = true;
|
||||||
|
|
||||||
const formData = new FormData(event.target as HTMLFormElement);
|
const formData = new FormData(event.target as HTMLFormElement);
|
||||||
const password = formData.get("password") as string;
|
const password = formData.get("newPassword") as string;
|
||||||
|
|
||||||
const resp = await fetch("/api/auth/reset-password", {
|
const resp = await fetch("/api/auth/reset-password", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -3235,9 +3235,6 @@
|
|||||||
<trans-unit id="sf151c44c3a52a448">
|
<trans-unit id="sf151c44c3a52a448">
|
||||||
<source>Enter new password</source>
|
<source>Enter new password</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
<trans-unit id="sf6c0a694575fb0a6">
|
|
||||||
<source>Must be between 8-64 characters</source>
|
|
||||||
</trans-unit>
|
|
||||||
<trans-unit id="s8daf047a917f4cc4">
|
<trans-unit id="s8daf047a917f4cc4">
|
||||||
<source>Choose a strong password between <x equiv-text="${PASSWORD_MINLENGTH}" id="0"/>-<x equiv-text="${PASSWORD_MAXLENGTH}" id="1"/> characters.</source>
|
<source>Choose a strong password between <x equiv-text="${PASSWORD_MINLENGTH}" id="0"/>-<x equiv-text="${PASSWORD_MAXLENGTH}" id="1"/> characters.</source>
|
||||||
</trans-unit>
|
</trans-unit>
|
||||||
|
Loading…
Reference in New Issue
Block a user