I need a way to break this loop or an alternative way to do this

I'm new to js and firebase. I'm trying to use firebase database for a custom login by using my own table called users. I have used a for each loop to go through the data. But the else part is executed multiple time because of this. I need to break the loop so it won't happen.

This is my data:-

{"users" : [ {
    "userId" : "1",
    "username" : "admin",
    "password" : "admin",
    "type" : "admin"
  }, {
    "userId" : "2",
    "username" : "cashier",
    "password" : "cashier",
    "type" : "cashier"  
  }]
}**

This is the code I wrote:

var database=firebase.database();

function SignIn(){
var txtuser=document.getElementById('username').value;
var txtpass=document.getElementById('password').value;
var error=false;

firebase.database().ref('users').orderByKey().once('value').then(function(snapshot) {
  snapshot.forEach(function(childSnapshot) {
    var users = childSnapshot.child('username').val();
    var pass=childSnapshot.child('password').val();

    if(txtuser==users && txtpass==pass){
      var type=childSnapshot.child('type').val();       
      if(type=="admin"){
        location.href="admin.html";
      }
      else if(type=="cashier"){
        location.href="cashier.html";
      }            
    }
    else{
      error=true;            
    }       
  });
});

if(error==true)
{
  window.alert("Invalid Credentials");
  location.href="index.html";
}
}

Upvotes: 0

Views: 91

Answers (2)

samthecodingman
samthecodingman

Reputation: 26171

Password Authentication

Instead of using your method of storing authentication details in the database, use the Sign in a user with an email address and password flow.

However, because you are using usernames not emails, append your storage bucket domain to the username (which will normally be PROJECT_ID.appspot.com).

So your "admin" and "cashier" users would become "admin@PROJECT_ID.appspot.com" and "cashier@PROJECT_ID.appspot.com". For the sake of email authentication, these are valid email addresses, even though they don't have inboxes.

You can then use firebase.auth() across your web app to manage your user's access control to pages like "admin.html" and "cashier.html".

Note: If you ever send out email to your users, make sure to omit emails that match "*@PROJECT_ID.appspot.com"

Answering the question

WARNING: Do not authenticate this way. Please use above method.

  • Passwords should never be stored in plain text
  • Passwords should never be stored in plain text
  • Users should never have access to another user's credentials in any database

For the sake of answering the question, you could use the following code:

var database=firebase.database();

function SignIn(){
    var txtuser=document.getElementById('username').value;
    var txtpass=document.getElementById('password').value;

    firebase.database().ref('users').orderByChild('username').equalTo(txtuser).once('value')
        .then(function(snapshot) {
            if (!snapshot.hasChildren()) {
                throw "username not found";
            } else if (snapshot.numChildren() != 1) {
                throw "duplicate usernames";
            }

            // only one child at this point, so only called once
            snapshot.forEach(function(childSnapshot) {
                if (pass != childSnapshot.child('password').val()) {
                    throw "password mismatch";
                }

                var type=childSnapshot.child('type').val();
                if(type=="admin") {
                    location.href = "admin.html";
                } else if(type=="cashier") {
                    location.href = "cashier.html";
                } else {
                    throw "unknown user type";
                }
            })
        })
        .catch(function(error) { // catches any errors thrown by promises
            location.href = "index.html";
        });
}

In the above code, each throw is caught by the Promise returned by the Firebase query. You can read up on Promises here.

Upvotes: 1

Davi
Davi

Reputation: 4147

Just check if error is set to true inside the .forEach and use return to "break" out:

var database=firebase.database();

function SignIn(){
  var txtuser=document.getElementById('username').value;
  var txtpass=document.getElementById('password').value;
  var error=false;

  firebase.database().ref('users').orderByKey().once('value').then(function(snapshot) {
    snapshot.forEach(function(childSnapshot) {
      var users, pass;
      
      if (error) { return; } // <-- "break" the "loop"
      
      users = childSnapshot.child('username').val();
      pass = childSnapshot.child('password').val();
      if(txtuser == users && txtpass == pass){
        var type=childSnapshot.child('type').val();       
        if(type == "admin"){
          location.href="admin.html";
        }
        else if(type == "cashier"){
          location.href="cashier.html";
        }            
      } else {
        error = true;            
      }       
    });

    if(error) {
      window.alert("Invalid Credentials");
      location.href="index.html";
    }
  });
}

Upvotes: 0

Related Questions