Raja Shekar Raja Shekar - 7 months ago 15
HTML Question

Json login with multiple user login in a single login page

I am trying to do a login form by using JSON, I have 3 different users to login in a single login page, they are as 1. User 2. Admin 3. Supplier
This is my code. I am doing this as a test case, I will change the authentication details to server side later on.

<html>
<head>
<title> Login Form</title>
<script>
function validate()
{
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var loginlist = { "User": {
"userlist":[{"username":"usr1", "password":"a123"},{"username":"usr2", "password":"a123"},{"username":"usr3", "password":"a123"}],
"ID":1
},
"Admin": {
"adminlist":[{"username":"admin1", "password":"b123"},{"username":"admin2", "password":"b123"},{"username":"admin3", "password":"b123"}],
"ID":2
},
"Supplier": {
"supplierlist":[{"username":"sup1", "password":"c123"},{"username":"sup2", "password":"c123"},{"username":"sup3", "password":"c123"}],
"ID":1
}
};
var logged = false;
if(loginlist[0].User.ID === 1){
for(var i =0; i < loginlist[0].User.userlist.length; i++){
if(username == loginlist[0].User.userlist[i].username && password == loginlist[0].User.userlist[i].password){
logged= true;
}
}
if(logged)
alert("User login");

else
alert("User login fail");

}
else if(loginlist[0].Admin.ID === 2){
for(var j =0; j < loginlist[0].Admin.adminlist.length; j++){
if(username == loginlist[0].Admin.adminlist[j].username && password == loginlist[0].Admin.adminlist[j].password){
logged= true;
}
}
if(logged)
alert("Admin login");

else
alert("admin login fail");

}
else{
for(var k =0; k < loginlist[0].Supplier.supplierlist.length; k++){
if(username == loginlist[0].Supplier.supplierlist[k].username && password == loginlist[0].Supplier.supplierlist[k].password){
logged= true;
}
}
if(logged)
alert("Supplier login");

else
alert("supplier login fail");

}
}
</script>
</head>
<body>
<div class="container">
<div class="main">
<h2>Login Form</h2>
<form id="form_id" method="post" name="myform">
<label>User Name :</label>
<input type="text" placeholder="Enter username" name="username" id="username"/>
<label>Password :</label>
<input type="password" placeholder="Enter Password" name="password" id="password"/>
<input type="button" value="Login" id="submit" onclick="validate()"/>
</form>
</body>
</html>


which I have tried. My issue is when I enter something into the username and password nothing is displaying, I have done this kind of program but with the single user operation. I am not able to achieve this multiple users in a single login page

Answer

I am not quite sure what is the reason for having each individual user type as separate arrays, it might be good for some specific use case, but it will certainly be more straightforward to have all users in a single set.

Having everything in one array and then providing some functions to use to fetch a specific user type would be a better approach, as this way you don't need to worry about the result so much from the beginning. Besides you should always be working with as much raw material as possible; though people might find this arguable.

It is usually better to not trigger JavaScript code in the <head> tag of the HTML unless it is needed, as the code is executed before all of the document is loaded. It is usually safer to put all JavaScript code just before the closing <body> tag.

I also noticed you were triggering the validate function on button click. It is a problem if you are submitting the form via any other method than that (e.g. pressing enter on a focused input field). I added an event listener to the form itself, this should handle all common submit cases.

I made the users array have just one level, which contains all of the users. Each user has a type, which is used to determine the type of the user (regular user, admin user, supplier, etc.)

I have commented each line of the code below.

This script should NOT be used in production of any kind. It is dangerous as all checks are done client-side and client-side only. ALWAYS use server-side checks, preferably in test scripts too!

Click the Run Snippet button below to test the script here.

You can find the usernames and passwords from the array in the very beginning of the JavaScript script.

// store the IDs of all logged in users in here
var loggedusers = [];

// server should handle everything below...
// users array, which contains all users in the system
// on the server-side this could be an array returned by a MySQL database table, for example
var users = [{
  // ID of the user
  id: 1,
  // username of the user
  username: 'user1',
  // password of the user, note that this should obviously be hashed on the server-side
  // for PHP back-end: preferably hashed with 'password_hash' and compared using 'password_verify' if using PHP version 5.5 or newer
  password: 'a',
  // type of the user, currently using 'user', 'admin' and 'supplier', but technically it could be _anything_
  type: 'user'
}, {
  id: 2,
  username: 'admin1',
  password: 'b',
  type: 'admin'
}, {
  id: 3,
  username: 'supplier1',
  password: 'c',
  type: 'supplier'
}];
// ... up to this point, never store this data on the client-side (especially highly sensitive information like hashes, salts, or even worse like plain text passwords like above).

/**
 * null|Object getUserByProperty ( mixed key, mixed value [ , boolean strict = false, boolean multiple = false, boolean case_insensitive = false ] )
 *
 * Gets a user by a property key, value and various settings.
 *
 * @param mixed key Property key to look for.
 * @param mixed value Property value to look for.
 * @param boolean strict (optional) Should the comparison be type strict?
 * @param boolean multiple (optional) Should it return all results, rather than the first result?
 * @param boolean case_insensitive (optional) Should it ignore character case?
 *
 * @return null|Object Returns the user object, or null, if not found.
 */
function getUserByProperty(key, value, strict, multiple, case_insensitive) {
  // prepare a result array
  var result = [];

  // loop through all of our users
  for (var index in users) {
    // get the user we are iterating through now
    var user = users[index];

    // check if the user has the specified property
    if (typeof user[key] != 'undefined') {
      // get the property value
      var compare = user[key];

      // doing something case insensitive
      if (case_insensitive) {
        // if the property value is a string
        if (typeof compare == 'string')
        // we want to turn it to lower case
          compare = compare.toLowerCase();

        // if the specified value is a string
        if (typeof value == 'string')
        // we want to turn it to lower case
          value = value.toLowerCase();
      }

      // if specified value is not defined, or values match
      if (typeof value == 'undefined' || ((strict && compare === value) || (!strict && compare == value))) {
        // if we want multiple results
        if (multiple) {
          // the result will be appended to the result array
          result.push(user);
        } else {
          // otherwise we just return it
          return user;
        }
      }
    }
  }

  // return the results or null, if nothing was found (for single match search)
  return multiple ? result : null;
}

/**
 * null|Object getUserById ( number id )
 *
 * Gets a user with the specified ID.
 *
 * @param number id ID of user to get.
 *
 * @return null|Object Returns the user object, or null, if not found.
 */
function getUserById(id) {
  return getUserByProperty('id', id);
}

/**
 * null|Object getUserByUsername ( string username [ , boolean case_insensitive = false ] )
 *
 * Gets a user with the specified username.
 *
 * @param string username Username of user to get.
 * @param boolean case_insensitive Should character case be ignored?
 *
 * @return null|Object Returns the user object, or null, if not found.
 */
function getUserByUsername(username, case_insensitive) {
  return getUserByProperty('username', username, false, false, case_insensitive);
}

/**
 * boolean|array getUsersByType ( string type [ , boolean case_insensitive = false ] )
 *
 * Gets all users with the specified type.
 *
 * @param string type Type of user to look for.
 * @param boolean case_insensitive Should character case be ignored?
 *
 * @return array Returns the an array of user objects.
 */
function getUsersByType(type, case_insensitive) {
  return getUserByProperty('type', type, false, true, case_insensitive);
}

/**
 * boolean|Object login ( string username, string password )
 *
 * Provides the functionality to be able to log in on a user.
 *
 * @param string username Username of the user to log in on.
 * @param string password Password of the user to log in on.
 *
 * @return boolean|Object Returns the user object, or false, if login was not successful.
 */
function login(username, password) {
  // checks whether username and password have been filled in
  if (typeof username == 'string' && typeof password == 'string' && username.length > 0 && password.length > 0) {
    // prepare a variable to store the user object, if any is received
    var loggeduser;

    // server should handle everything below...
    // iterate through all users in the 'users' array (or database table perhaps, on server-side)
    for (var index in users) {
      // grab the property value with the property
      var user = users[index];

      // check if username and password match
      if (username === user.username && password === user.password)
      // set value of 'loggeduser' to the property value (user)
        loggeduser = user;
    }
    // ... up to this point, and the user returned from the server should be set in to 'loggeduser'
    // make sure highly sensitive information is not returned, such as hash, salt or anything

    // check whether the user is set
    if (typeof loggeduser != 'undefined') {
      // save the ID of the user to the 'loggedusers' array
      loggedusers[loggeduser.id] = true;

      // update the logged in list
      updatelist();

      // return the received user object
      return loggeduser;
    }
  }

  return false;
}

/**
 * boolean logout ( number userid )
 *
 * Provides the functionality to be able to log out from a user.
 *
 * @param number userid ID of the user to log out of.
 *
 * @return boolean Returns a boolean representing whether the log out was successful or not.
 */
function logout(userid) {
  // check whether the ID is actually logged in
  if (loggedusers[userid]) {
    // temporary array, which we will be filling
    var temporary = [];

    // let's loop through logged users
    for (var id in loggedusers)
    // ignore our user
      if (id != userid)
      // let's put this user to the array
        temporary[id] = true;

      // we replace the 'loggedusers' array with our new array
    loggedusers = temporary;

    // update the logged in list
    updatelist();

    // we have successfully logged out
    return true;
  }

  // we have not successfully logged out
  return false;
}

/**
 * boolean updatelist ( void )
 *
 * Provides the functionality to update the #logged-in-list element
 * with the logged in users names and logout links.
 *
 * @return boolean Returns a boolean representing whether the update was successful or not.
 */
function updatelist() {
  // get the #logged-in-list element
  var list_element = document.getElementById('logged-in-list');

  // check the element exists 
  if (list_element) {
    // get the #logged-in element
    var list_container_element = document.getElementById('logged-in');

    // check the element exists and that we should be changing the styles
    if (list_container_element)
    // if there are no logged in users, "hide" the element, otherwise "show" it
      list_container_element.style.visibility = loggedusers.length === 0 ? 'hidden' : 'visible';

    // we take the first child with a while loop
    while (list_element.firstChild)
    // remove the child, and it will repeat doing so until there is no firstChild left for the list_element
      list_element.removeChild(list_element.firstChild);

    // we loop through every logged in user
    for (var id in loggedusers) {
      // get the user by ID
      var user = getUserById(id);

      // check if that user is a user
      if (user) {
        // we create necessary elements to cover our logout functionality
        var p = document.createElement('P');
        p.innerText = user.username;
        var a = document.createElement('A');
        a.userid = id;
        a.href = '#';
        a.innerHTML = '(logout)';

        // we bind an onclick event listener to the link
        a.addEventListener('click', function(e) {
          e.preventDefault();

          // we will now execute the logout function for this user ID
          logout(e.srcElement.userid);
        });

        // we append the link to the paragraph element
        p.appendChild(a);

        // we append the paragraph to the list element
        list_element.appendChild(p);
      }
    }

    return true;
  }

  return false;
}

// add a new 'onsubmit' event listener to the '#login-form' node
// this will be triggered each time the form is submitted via any method
document.getElementById('login-form').addEventListener('submit', function(e) {
  // prevent default browser behavior
  e.preventDefault();

  // find the username and password nodes
  var username_element = e.srcElement.elements.username;
  var password_element = e.srcElement.elements.password;

  // check whether these elements return right stuff
  if (username_element && password_element) {
    // get the values of username and password
    username = username_element.value;
    password = password_element.value;

    // execute the 'login' function with the username and password filled in on the client
    var user = login(username, password);

    // check whether the login was successful
    if (user !== false) {
      // reset the username input field
      username_element.value = '';

      // reset the password input field
      password_element.value = '';

      // alert the client that login was successful
      alert('Logged in as ' + user.username + '.');
    } else {
      // reset the password input field
      password_element.value = '';

      // alert the client that login was not successful
      alert('Invalid username and/or password.');
    }
  }
});
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />

  <title>Login Form</title>
</head>

<body>
  <div style="visibility: hidden;" id="logged-in">
    <p><strong>Logged in as:</strong>
    </p>
    <div id="logged-in-list"></div>
  </div>

  <form id="login-form">
    <h2>Login Form</h2>

    <label for="username">Username:</label>
    <input type="text" placeholder="Enter username..." id="username" />

    <label for="password">Password:</label>
    <input type="password" placeholder="Enter password..." id="password" />

    <input type="submit" value="Login" />
  </form>

  <!-- the JavaScript code should go as contents of this tag -->
  <script></script>
</body>

</html>

Please, to anyone using this code, do not use this, under any circumstance, in production. Always perform validations and comparisons server-side, along with client-side checks before the server-side checks to cut out any unnecessary processing on the server.

Hope this helps you!