A Simple Guide to Implement Hashing into your Knack APPs

 

Skills: JavaScript, JQuery, AJAX, HTMLLevel: Medium

Hello Folks!

If you ever need to store sensitive information in the database, we advise you to try the solution based on data encryption or hashing, which in summary converts a value into an encrypted string of numbers and characters.

Let's suppose we want to store people's IDs in our database, but we don't want to save the ID in the database in plain text for the world to see. Yet, we want the ID to be searchable from a Knack.

Today we’ll show you the exact steps you’ll need to know to incorporate the Hashing technique into your Knack applications.

To see a working example, follow these link

Remember to always follow this guide:

1. Set up the Object and Field in Knack.

To start, let’s set up an object in Knack with two fields, the field where the hash code will be saved, in our example the ID of the person, and the field with the name of the person that will be retrieved.

LIBRARY HASH ID NUMBERS.png

Make sure to mark the “Identification number” field as mandatory (*); this will let the user know they must enter the information before saving it. 

 
2. Add the Search and Insert forms to your page.

ID NUMBER HASH.png
SEARCH ID NUMBER.png

3. Add the JavaScript code 

Invoke the MD5 Library

You’ll need to invoke a hashing library using JavaScript. The library used in this example is found here https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.13.0/js/md5.min.js

LazyLoad.js(['https://cdnjs.cloudflare.com/ajax/libs/blueimp-md5/2.13.0/js/md5.min.js'], function () {
// your code will go here
});

Insert:

Once you have the hashing library ready, you need to capture the knack-form-submit event of the form so the person ID is converted to an encrypted hashed value before it’s saved in the database.

// Insert with Hash
            $(document).on('knack-form-submit.view_345', async function (event, view, data) {
                await update(lib.OBJECTS_IDS.hashes, data.id, JSON.stringify(
                    {
                        field_382: md5(data.field_382)
                    }
                ));

            });
const update = function (objectId, id, data) 
                var dfd = $.Deferred();            
                $.ajax({
                type: 'PUT',
                headers: this.headers,
                  url:  this.knackURL + 'objects/' + objectId + '/records/' + id,
                  data: data,
                  triedCount: 0,
                  retryLimit: 3,
                  error: function(xhr, textStatus, errorThrown ) {
                  console.log("error: " + this.triedCount);
                  this.triedCount++;
                  if (this.triedCount < this.retryLimit && xhr.status >= 500) {

                  console.log(this);
                  $.ajax(this);
                  } else{
                  dfd.reject(xhr);
                  }

                  },

                  success: function (response) {

                  dfd.resolve(response);

                  }

                  });            

                  return dfd.promise();

                 };

Search:

Likewise, you’ll need to capture the ‘click’ event in the Search button so that value to search is hashed before the code looks for the match in the database.

// Search by Hash
          $(document).on('knack-view-render.view_339', function (e, v) {
                $('#view_339 button').on('click', async function (e) {
                e.preventDefault()
                    let val = $('#field_382').val()
                    let hash = md5(val)
                    let result = await find(lib.OBJECTS_IDS.hashes, [{

                        field: 'field_382',
                        operator: 'is',
                        value: hash

                    }])

                    if (result.records.length > 0) {
                    let userName = result.records[0].field_376
                    if ($('#result').length) {

                            $('#result').html(`<b>User:</b> ${userName}`)
                    } else {
                           $('#view_339 #kn-input-field_382').append(`<span id="result"><b>User:</b> ${userName}</span>`)

                        }
                    } else {
                        if ($('#result').length) {
                            $('#result').html('User not found')
                        } else {
                            $('#view_339 #kn-input-field_382').append(`<span id="result">User not found</span>`)
                        }
                    }
                });
            });
 const find = function (objectId, filters, sortField, sortOrder, recordPerPage) {

                filters = filters || [];
                sortOrder = sortOrder || '';
                sortField = sortField || '';
                recordPerPage = recordPerPage || 'all';            
                var filterValEnc = encodeURIComponent(JSON.stringify(filters));
                var sortFEnc = encodeURIComponent(sortField);
                var sortOEnc = encodeURIComponent(sortOrder);                         var dfd = $.Deferred();            

                $.ajax({
                    type: 'GET',
                    headers: this.headers,
                    url:  this.knackURL + 'objects/' + objectId + '/records?rows_per_page=' + recordPerPage +
                            '&filters=' + filterValEnc + "&sort_field=" + sortFEnc + "&sort_order=" +
                            sortOEnc,

                    triedCount: 0,
                    retryLimit: 3,
                    error: function(xhr, textStatus, errorThrown ) {
                        console.log("error: " + this.triedCount);
                        this.triedCount++;
                        if (this.triedCount < this.retryLimit && xhr.status >= 500) {

                            console.log(this);
                            $.ajax(this);
                        } else{
                            dfd.reject(xhr);
                        }
                    },
                    success: function (response) {
                        dfd.resolve(response);
                    }
                });            
                return dfd.promise();
            };

Did you find this insightful?

Please leave a comment below and let us know!

Make IT Happen!