mirror of
				https://github.com/pierre42100/ComunicWeb
				synced 2025-11-04 12:14:12 +00:00 
			
		
		
		
	Apply password policy on sign up screen
This commit is contained in:
		@@ -7,7 +7,7 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Check if it is Manon's birthday
 | 
			
		||||
 */
 | 
			
		||||
async function checkManonBirthday(force) {
 | 
			
		||||
/*async function checkManonBirthday(force) {
 | 
			
		||||
 | 
			
		||||
	if(force !== true) {
 | 
			
		||||
		// Manon's feature only
 | 
			
		||||
@@ -69,4 +69,4 @@ document.addEventListener("wsOpen", () => {
 | 
			
		||||
	setTimeout(() => checkManonBirthday(), 1000);
 | 
			
		||||
}, {
 | 
			
		||||
	once: true
 | 
			
		||||
})
 | 
			
		||||
})*/
 | 
			
		||||
							
								
								
									
										209
									
								
								assets/js/components/passwordInput.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								assets/js/components/passwordInput.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,209 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Password input field
 | 
			
		||||
 * 
 | 
			
		||||
 * @author Pierre Hubert
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
class PasswordInput {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create password input field
 | 
			
		||||
     * 
 | 
			
		||||
     * @param {HTMLElement} target The target for the password input
 | 
			
		||||
     * @param {String} label The label for the input
 | 
			
		||||
     * @param {String} placeholder The placeholder to use
 | 
			
		||||
     */
 | 
			
		||||
    constructor(target, label, placeholder) {
 | 
			
		||||
        this._input = createFormGroup({
 | 
			
		||||
			target: target,
 | 
			
		||||
			label: label,
 | 
			
		||||
			placeholder: placeholder,
 | 
			
		||||
			type: "password",
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
        this._input.parentNode.parentNode.classList.add("password-input-group");
 | 
			
		||||
 | 
			
		||||
        this._input.addEventListener("keyup", () => this._refreshArea());
 | 
			
		||||
        this._input.addEventListener("change", () => this._refreshArea());
 | 
			
		||||
 | 
			
		||||
        this.helpArea = createElem2({
 | 
			
		||||
            appendTo: this._input.parentNode,
 | 
			
		||||
            type: "span",
 | 
			
		||||
            class: "help-block"
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this._init();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async _init() {
 | 
			
		||||
        try {
 | 
			
		||||
            await ServerConfig.ensureLoaded()
 | 
			
		||||
            this._ready = true;
 | 
			
		||||
            this._valid = false;
 | 
			
		||||
            this._refreshArea();
 | 
			
		||||
        } catch(e) {
 | 
			
		||||
            console.error(e);
 | 
			
		||||
            notify(tr("Failed to load server configuration! Please reload the page!"), "danger");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setFirstName(firstName) {
 | 
			
		||||
        this._firstName = firstName;
 | 
			
		||||
        this._refreshArea();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setLastName(lastName) {
 | 
			
		||||
        this._lastName = lastName;
 | 
			
		||||
        this._refreshArea();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setEmail(email) {
 | 
			
		||||
        this._email = email.length > 2 ? email : null;
 | 
			
		||||
        this._refreshArea();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isValid() {
 | 
			
		||||
        this._refreshArea();
 | 
			
		||||
        return this._valid;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _refreshArea() {
 | 
			
		||||
        if (!this._ready)
 | 
			
		||||
            return;
 | 
			
		||||
        
 | 
			
		||||
        this.helpArea.innerHTML = "";
 | 
			
		||||
        
 | 
			
		||||
        /** @type {String} */
 | 
			
		||||
        const password = this._input.value.trim().toLowerCase();
 | 
			
		||||
        const policy = ServerConfig.conf.password_policy;
 | 
			
		||||
 | 
			
		||||
        if (password.length == 0) {
 | 
			
		||||
            this._valid = false;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this._good = [];
 | 
			
		||||
        this._bad = [];
 | 
			
		||||
 | 
			
		||||
        // Check email
 | 
			
		||||
        this._performMandatoryCheck(
 | 
			
		||||
            tr("Password must not contains part of email address"),
 | 
			
		||||
            !policy.allow_email_in_password && this._email,
 | 
			
		||||
            () => !password.includes(this._email.toLowerCase()) && !this._email.toLowerCase().includes(password)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Check name
 | 
			
		||||
        this._performMandatoryCheck(
 | 
			
		||||
            tr("Password must not contains part of name"),
 | 
			
		||||
            !policy.allow_name_in_password && this._firstName && this._lastName,
 | 
			
		||||
            () => !password.includes(this._firstName.toLowerCase()) && !password.includes(this._lastName)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Check password length
 | 
			
		||||
        this._performMandatoryCheck(
 | 
			
		||||
            tr("Password must be composed of at least %num_chars% characters", {num_chars: policy.min_password_length}),
 | 
			
		||||
            true,
 | 
			
		||||
            () => password.length >= policy.min_password_length
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Check if mandatory arguments are respected
 | 
			
		||||
        this._valid = this._bad.length == 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // Check categories presence
 | 
			
		||||
        if(policy.min_categories_presence > 0) {
 | 
			
		||||
 | 
			
		||||
            let count = 0
 | 
			
		||||
 | 
			
		||||
            this._performCategoryCheck(
 | 
			
		||||
                this._input.value,
 | 
			
		||||
                tr("At least %num% upper case character", {num: policy.min_number_upper_case_letters}),
 | 
			
		||||
                "[A-Z]",
 | 
			
		||||
                policy.min_number_upper_case_letters
 | 
			
		||||
            ) && count++
 | 
			
		||||
 | 
			
		||||
            this._performCategoryCheck(
 | 
			
		||||
                this._input.value,
 | 
			
		||||
                tr("At least %num% lower case character", {num: policy.min_number_lower_case_letters}),
 | 
			
		||||
                "[a-z]",
 | 
			
		||||
                policy.min_number_lower_case_letters
 | 
			
		||||
            ) && count++
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            this._performCategoryCheck(
 | 
			
		||||
                password,
 | 
			
		||||
                tr("At least %num% digit character", {num: policy.min_number_digits}),
 | 
			
		||||
                "[0-9]",
 | 
			
		||||
                policy.min_number_digits
 | 
			
		||||
            ) && count++
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            this._performCategoryCheck(
 | 
			
		||||
                password,
 | 
			
		||||
                tr("At least %num% special character", {num: policy.min_number_special_characters}),
 | 
			
		||||
                "[^0-9a-zA-Z]",
 | 
			
		||||
                policy.min_number_special_characters
 | 
			
		||||
            ) && count++
 | 
			
		||||
 | 
			
		||||
            if (count < policy.min_categories_presence)
 | 
			
		||||
                this._valid = false;
 | 
			
		||||
            
 | 
			
		||||
            if (policy.min_categories_presence < 4)
 | 
			
		||||
                this._performMandatoryCheck(
 | 
			
		||||
                    tr(
 | 
			
		||||
                        "At least %num% of the following : upper case letter, lower case letter, digit or special character",
 | 
			
		||||
                        {num: policy.min_categories_presence}
 | 
			
		||||
                    ),
 | 
			
		||||
                    true,
 | 
			
		||||
                    () => count >= policy.min_categories_presence
 | 
			
		||||
                );
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        if (this._valid) {
 | 
			
		||||
            this.helpArea.innerHTML = tr("You can use this password");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for(let bad of this._bad)
 | 
			
		||||
            this._addTip(false, bad);
 | 
			
		||||
 | 
			
		||||
        for(let good of this._good)
 | 
			
		||||
            this._addTip(true, good);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _performMandatoryCheck(check_label, requisite, check) {
 | 
			
		||||
        if (!requisite)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        const pass = check();
 | 
			
		||||
        if (!pass)
 | 
			
		||||
            this._bad.push(check_label);
 | 
			
		||||
        
 | 
			
		||||
        else
 | 
			
		||||
            this._good.push(check_label);
 | 
			
		||||
        
 | 
			
		||||
        return pass;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _performCategoryCheck(password, check_label, regex, numRequired) {
 | 
			
		||||
        if (numRequired < 1)
 | 
			
		||||
            return true;
 | 
			
		||||
        
 | 
			
		||||
        const pass = [...password.matchAll(regex)].length >= numRequired;
 | 
			
		||||
 | 
			
		||||
        if (!pass)
 | 
			
		||||
            this._bad.push(check_label);
 | 
			
		||||
        
 | 
			
		||||
        else
 | 
			
		||||
            this._good.push(check_label);
 | 
			
		||||
        
 | 
			
		||||
        return pass;
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _addTip(isGood, content) {
 | 
			
		||||
        this.helpArea.innerHTML += "<i class='fa "+(isGood ? "fa-check": "fa-close ")+"'></i> " + content + "<br />";
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user