Jam.py documentation

How to give user ability to change the password

First we create a “Change password” item. While creating it we set the “Virtual table” and “Visible” attributes to false in the Item Editor Dialog. And we add to it two fields: “Old password”, “New password”

We’ll use this item for displaying “Change password” dialog.

To open this dialog we add a “Change password” menu item with id “pass” in the index.html:

<div class="container">
    <div id="taskmenu" class="navbar">
        <div class="navbar-inner">
            <ul id="menu" class="nav">
            </ul>
            <ul id="menu-right" class="nav pull-right">
                <li id="pass"><a href="#">Change password</a></li>
            </ul>
        </div>
    </div>
</div>

and in the task client module on_page_loaded event handler add the following code:

if (task.change_password.can_view()) {
    $("#menu-right #pass a").click(function(e) {
        e.preventDefault();
        task.change_password.open({open_empty: true});
        task.change_password.append_record();
    });
}
else {
    $("#menu-right #pass a").hide();
}

It will check if the user has the right to view item and then opens an empty dataset and creates an edit form, otherwise it hides this menu item.

In the “Change password” client module we add the following code:

function on_edit_form_created(item) {
    item.edit_form.find("#ok-btn")
        .off('click.task')
        .on('click', function() {
            change_password(item);
        });
    item.edit_form.find("#cancel-btn")
        .off('click.task')
        .on('click', function() {
            item.close_edit_form();
        });
}

function change_password(item) {
    item.post();
    item.server('change_password', [item.old_password.value, item.new_password.value], function(res) {
        if (res) {
            item.warning('Password has been changed. <br> The application will be reloaded.',
              function() {
                  task.logout();
                  location.reload();
              });
        }
        else {
            item.alert_error("Can't change the password.");
            item.edit();
        }
    });
}

function on_field_changed(field, lookup_item) {
    var item = field.owner;
    if (field.field_name === 'old_password') {
        item.server('check_old_password', [field.value], function(error) {
            if (error) {
                item.alert_error(error);
            }
        });
    }
}

function on_edit_form_close_query(item) {
    return true;
}

In it we reassign OK and Cancel button click events. By default they are defined in the task client module to save record changes to the database and cancel editing. In the on_edit_form_close_query even handler we return true so the on_edit_form_close_query declared in the task client module, that shows “Yes No Cancel” disalog won’t be executed.

The on_field_changed event handler will check if old password is correct. It and the change_password function send requests to the server to execute functions defined in the item server module:

def change_password(item, old_password, new_password):
    user_id = item.session['user_info']['user_id']
    users = item.task.users.copy(handlers=False)
    users.set_where(id=user_id)
    users.open()
    same_password = item.task.check_password_hash(users.password_hash.value, old_password)
    if users.rec_count== 1 and same_password:
        users.edit()
        users.password_hash.value = item.task.generate_password_hash(new_password)
        users.post()
        users.apply()
        return True
    else:
        return False

def check_old_password(item, old_password):
    user_id = item.session['user_info']['user_id']
    users = item.task.users.copy(handlers=False)
    users.set_where(id=user_id)
    users.open()
    same_password = item.task.check_password_hash(users.password_hash.value, old_password)
    if users.rec_count == 1 and same_password:
        return
    else:
        return 'Invalid password'

They use session to get id of the current user.

After changing the password the client reloads.