@@ -72,7 +72,8 @@ import {
72
72
getRedirectResult ,
73
73
browserPopupRedirectResolver ,
74
74
connectAuthEmulator ,
75
- initializeRecaptchaConfig
75
+ initializeRecaptchaConfig ,
76
+ validatePassword
76
77
} from '@firebase/auth' ;
77
78
78
79
import { config } from './config' ;
@@ -493,6 +494,93 @@ function onInitializeRecaptchaConfig() {
493
494
initializeRecaptchaConfig ( auth ) ;
494
495
}
495
496
497
+ /**
498
+ * Updates the displayed validation status for the inputted password.
499
+ */
500
+ function onValidatePassword ( ) {
501
+ /**
502
+ * Updates the displayed status for a requirement.
503
+ * @param {string } id The ID of the DOM element displaying the requirement status.
504
+ * @param {boolean | undefined } status Whether the requirement is met.
505
+ */
506
+ function setRequirementStatus ( id , status ) {
507
+ // Hide the requirement if the status does not include it.
508
+ if ( status === undefined ) {
509
+ $ ( id ) . hide ( ) ;
510
+ return ;
511
+ }
512
+
513
+ if ( status ) {
514
+ $ ( id ) . removeClass ( 'list-group-item-danger' ) ;
515
+ $ ( id ) . addClass ( 'list-group-item-success' ) ;
516
+ } else {
517
+ $ ( id ) . removeClass ( 'list-group-item-success' ) ;
518
+ $ ( id ) . addClass ( 'list-group-item-danger' ) ;
519
+ }
520
+ $ ( id ) . show ( ) ;
521
+ }
522
+
523
+ const password = $ ( '#password-validation-password' ) . val ( ) ;
524
+ validatePassword ( auth , password ) . then (
525
+ status => {
526
+ const passwordPolicy = status . passwordPolicy ;
527
+ const customStrengthOptions = passwordPolicy . customStrengthOptions ;
528
+
529
+ // Only show options required by the password policy.
530
+ if ( customStrengthOptions . minPasswordLength ) {
531
+ $ ( '#password-validation-min-length' ) . text (
532
+ customStrengthOptions . minPasswordLength
533
+ ) ;
534
+ }
535
+ if ( customStrengthOptions . maxPasswordLength ) {
536
+ $ ( '#password-validation-max-length' ) . text (
537
+ customStrengthOptions . maxPasswordLength
538
+ ) ;
539
+ }
540
+ if ( customStrengthOptions . containsNonAlphanumericCharacter ) {
541
+ $ ( '#password-validation-allowed-non-alphanumeric-characters' ) . attr (
542
+ 'data-original-title' ,
543
+ passwordPolicy . allowedNonAlphanumericCharacters
544
+ ) ;
545
+ }
546
+ Object . keys ( status ) . forEach ( requirement => {
547
+ if ( requirement !== 'passwordPolicy' ) {
548
+ // Get the requirement ID by converting to kebab case.
549
+ const requirementIdPrefix = '#password-validation-' ;
550
+ const requirementId =
551
+ requirementIdPrefix +
552
+ requirement . replace ( / [ A - Z ] / g, match => '-' + match . toLowerCase ( ) ) ;
553
+
554
+ setRequirementStatus ( requirementId , status [ requirement ] ) ;
555
+ }
556
+ } ) ;
557
+
558
+ $ ( '#password-validation-password' ) . prop ( 'disabled' , false ) ;
559
+ $ ( '#password-validation-requirements' ) . show ( ) ;
560
+ } ,
561
+ error => {
562
+ // Disable the password input and hide the requirements since validation cannot be performed.
563
+ if ( error . code === `auth/unsupported-password-policy-schema-version` ) {
564
+ $ ( '#password-validation-password' ) . prop ( 'disabled' , true ) ;
565
+ }
566
+ $ ( '#password-validation-requirements' ) . hide ( ) ;
567
+ onAuthError ( error ) ;
568
+ }
569
+ ) ;
570
+ }
571
+
572
+ /**
573
+ * Toggles text visibility for the password validation input field.
574
+ */
575
+ function onToggleViewPasswordForValidation ( ) {
576
+ const id = '#password-validation-password' ;
577
+ if ( $ ( id ) . prop ( 'type' ) === 'password' ) {
578
+ $ ( id ) . prop ( 'type' , 'text' ) ;
579
+ } else {
580
+ $ ( id ) . prop ( 'type' , 'password' ) ;
581
+ }
582
+ }
583
+
496
584
/**
497
585
* Signs in with a generic IdP credential.
498
586
*/
@@ -2033,6 +2121,10 @@ function initApp() {
2033
2121
$ ( '#sign-in-anonymously' ) . click ( onSignInAnonymously ) ;
2034
2122
$ ( '.set-tenant-id' ) . click ( onSetTenantID ) ;
2035
2123
$ ( '#initialize-recaptcha-config' ) . click ( onInitializeRecaptchaConfig ) ;
2124
+ $ ( '#password-validation-password' ) . keyup ( onValidatePassword ) ;
2125
+ $ ( '#password-validation-view-password' ) . click (
2126
+ onToggleViewPasswordForValidation
2127
+ ) ;
2036
2128
$ ( '#sign-in-with-generic-idp-credential' ) . click (
2037
2129
onSignInWithGenericIdPCredential
2038
2130
) ;
0 commit comments