mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	login: Add show password feature to login page.
The show password feature is a functionality to toggle the visibility of the password fields in forms so that one can check if they have entered the correct password or not. We implement this using an eye icon toggling which converts input field type from password to text and vice-versa. Fixes part of #17301.
This commit is contained in:
		
				
					committed by
					
						
						Tim Abbott
					
				
			
			
				
	
			
			
			
						parent
						
							2ceda13e31
						
					
				
				
					commit
					fa235e60ff
				
			@@ -221,4 +221,14 @@ to test 2FA in development, make sure that you login using a
 | 
			
		||||
password.  You can get the passwords for the default test users using
 | 
			
		||||
`./manage.py print_initial_password`.
 | 
			
		||||
 | 
			
		||||
## Password form implementation
 | 
			
		||||
 | 
			
		||||
By default, Zulip uses `autocomplete=off` for password fields where we
 | 
			
		||||
enter the current password, and `autocomplete="new-password"` for
 | 
			
		||||
password fields where we create a new account or change the existing
 | 
			
		||||
password.  This prevents the browser from auto-filling the existing
 | 
			
		||||
password.
 | 
			
		||||
 | 
			
		||||
Visit <https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete> for more details.
 | 
			
		||||
 | 
			
		||||
[0]: https://github.com/Bouke/django-two-factor-auth
 | 
			
		||||
 
 | 
			
		||||
@@ -128,3 +128,33 @@ run_test("adjust_mac_shortcuts mac", (override) => {
 | 
			
		||||
        assert.equal(test_item.stub.text(), test_item.mac_key);
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
run_test("show password", () => {
 | 
			
		||||
    const password_selector = ".password_visibility_toggle";
 | 
			
		||||
 | 
			
		||||
    function set_attribute(type) {
 | 
			
		||||
        $("#id_password").attr("type", type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function check_assertion(type, present_class, absent_class) {
 | 
			
		||||
        assert.equal($("#id_password").attr("type"), type);
 | 
			
		||||
        assert($(password_selector).hasClass(present_class));
 | 
			
		||||
        assert(!$(password_selector).hasClass(absent_class));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const ev = {
 | 
			
		||||
        preventDefault: () => {},
 | 
			
		||||
        stopPropagation: () => {},
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    set_attribute("password");
 | 
			
		||||
    common.setup_password_visibility_toggle("#id_password", password_selector);
 | 
			
		||||
 | 
			
		||||
    const handler = $(password_selector).get_on_handler("click");
 | 
			
		||||
 | 
			
		||||
    handler(ev);
 | 
			
		||||
    check_assertion("text", "fa-eye", "fa-eye-slash");
 | 
			
		||||
 | 
			
		||||
    handler(ev);
 | 
			
		||||
    check_assertion("password", "fa-eye-slash", "fa-eye");
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -134,3 +134,27 @@ export function adjust_mac_shortcuts(key_elem_class, require_cmd_style) {
 | 
			
		||||
        $(this).text(key_text);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// See https://zulip.readthedocs.io/en/latest/development/authentication.html#password-form-implementation
 | 
			
		||||
// for design details on this feature.
 | 
			
		||||
//
 | 
			
		||||
// This toggle code would probably be cleaner as 2 functions.
 | 
			
		||||
function toggle_password_visibility(password_field_id, password_selector) {
 | 
			
		||||
    const password_field = $(password_field_id);
 | 
			
		||||
 | 
			
		||||
    if (password_field.attr("type") === "password") {
 | 
			
		||||
        password_field.attr("type", "text");
 | 
			
		||||
        $(password_selector).removeClass("fa-eye-slash").addClass("fa-eye");
 | 
			
		||||
    } else {
 | 
			
		||||
        password_field.attr("type", "password");
 | 
			
		||||
        $(password_selector).removeClass("fa-eye").addClass("fa-eye-slash");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function setup_password_visibility_toggle(password_field_id, password_selector) {
 | 
			
		||||
    $(password_selector).on("click", (e) => {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
        e.stopPropagation();
 | 
			
		||||
        toggle_password_visibility(password_field_id, password_selector);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,11 @@ $(() => {
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    common.setup_password_visibility_toggle(
 | 
			
		||||
        "#id_password",
 | 
			
		||||
        "#id_password ~ .password_visibility_toggle",
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    function highlight(class_to_add) {
 | 
			
		||||
        // Set a class on the enclosing control group.
 | 
			
		||||
        return function (element) {
 | 
			
		||||
 
 | 
			
		||||
@@ -120,3 +120,18 @@ i.zulip-icon.bot {
 | 
			
		||||
     */
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.password-div {
 | 
			
		||||
    position: relative;
 | 
			
		||||
 | 
			
		||||
    .password_visibility_toggle {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        right: 10px;
 | 
			
		||||
        top: 42px;
 | 
			
		||||
        opacity: 0.6;
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
            opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -67,11 +67,12 @@ page can be easily identified in it's respective JavaScript file. -->
 | 
			
		||||
                                </label>
 | 
			
		||||
                            </div>
 | 
			
		||||
 | 
			
		||||
                            <div class="input-box no-validation">
 | 
			
		||||
                                <input id="id_password" name="password" class="required" type="password"
 | 
			
		||||
                            <div class="input-box no-validation password-div">
 | 
			
		||||
                                <input id="id_password" name="password" class="required" type="password" autocomplete="off"
 | 
			
		||||
                                  {% if email %} autofocus {% endif %}
 | 
			
		||||
                                  required />
 | 
			
		||||
                                <label for="id_password" class="control-label">{{ _('Password') }}</label>
 | 
			
		||||
                                <i class="fa fa-eye-slash password_visibility_toggle" role="button" title="{{ _('Toggle password visibility') }}" aria-label="{{ _('Toggle password visibility') }}"></i>
 | 
			
		||||
                            </div>
 | 
			
		||||
                            {% else %}
 | 
			
		||||
                            {% include "two_factor/_wizard_forms.html" %}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user