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