How to check if usernames are unique in Firebase - javascript

I have a function (not finished yet) that should check if a username already exists/is unique in my Firebase database. I have searched Google on how to implement this and I have managed to get the below. Unfortunately, it doesn't work and I don't even get any console.logs. Any help is appreciated - what exactly am I doing wrong?
onChangeUsername = (event) => {
var oldError = {...this.state.error};
firebase.database().ref().child("Usernames").orderByValue().once('value', (snapshot) => {
var exists = (snapshot.val() !== null);
console.log(exists);
console.log("hello");
});
if(this.state.validation.username.unique===true)
{oldError.username = "This username is already taken"}
else if((event.nativeEvent.text.length<this.state.validation.username.min) || (event.nativeEvent.text.length>this.state.validation.username.max) )
{oldError.username = "Username should be between " + this.state.validation.username.min + " and " + this.state.validation.username.max + " characters" ;}
else oldError.username = "";
this.setState({ username: event.nativeEvent.text, error:oldError })
}
my database structure is as follows:
Database:{ Usernames: {uid1: username1, uid2: username2}}
****Question Update ****
After Comments from Frank, I have changed my code to the following. It still doesn't work, but my he has spotted a couple of errors that needed fixing:
onChangeUsername = (event) => {
var oldError = {...this.state.error};
firebase.database().ref().child("Usernames").orderByKey().equalTo("Username1").once('value', (snapshot) => {
var exists = (snapshot.val() !== null);
console.log(exists);
console.log("hello");
});
if(this.state.validation.username.unique===true)
{oldError.username = "This username is already taken"}
else if((event.nativeEvent.text.length<this.state.validation.username.min) || (event.nativeEvent.text.length>this.state.validation.username.max) )
{oldError.username = "Username should be between " + this.state.validation.username.min + " and " + this.state.validation.username.max + " characters" ;}
else oldError.username = "";
this.setState({ username: event.nativeEvent.text, error:oldError })
}
and my database to the following:
Database:{ Usernames: {Username1: uid1, Username2: uid2}}

You're missing a comparison in your query:
firebase.database().ref().child("Usernames").equalTo("Username1").orderByValue()
I recommend btw inverting the data structure. If you want user names to be unique, use those as the keys in the parent node:
Database:{
Usernames: {
Username1: uidOfUserWithUsername1,
Username2: uidOfUserWithUsername2
}
}
This way your lookups will be simpler and fast, since you don't need a query. In addition, the value will now allow you to easily look up more information on the user who claimed this user name.

Related

Comparing two arrays for usernames + passwords

I have two arrays in JavaScript. One contains usernames and one contains passwords. I want to create a loop that checks what position (i) the username is in - in the 'approvedUsernames' array - that was inputted by the user, and takes that same 'i' value in the 'approvedPasswords' array and picks the value that was found. then compare the two. If they match, a successful login happens, if not it is unsuccessful
Please see existing Arrays and the code i have already written below
any help greatly appreciated
i hope this was clear enough i had trouble wording it :)
James
EDIT: I KNOW THIS IS A VERY INSECURE WAY TO STORE PASSWORDS IT IS JUST TEMPORARY TO TEST THE LOGIN ALGORITHM. THE FINAL VERSION WILL DEFINITELY BE USING PHP+SQL DATABASE
Arrays:
approvedLogins = ['JamesLiverton', 'SamW'] approvedPasswords = ['password', 'coding']
Code:
function login(){
var username = document.getElementById('usernameField').value
var password = document.getElementById('passwordField').value
for (i = 0; i < approvedLogins.length; i++) {
if (username == approvedLogins[i].username && password == approvedPasswords[i].password) {
alert('Login Sucessful')
return
}
else {
alert('Login Unsucessful')
return
}
}
}
First, if you're planning on doing this, I have a feeling that you don't know much about security. I suggest you look into third party authentication (which, if you're asking this kind of question, might be out of your skill level, but still). At the very least, consider encrypting your user's password, with a salt (look up what a salt is).
With that said, you can do this.
function login() {
const username = document.getElementById('usernameField').value
const password = document.getElementById('passwordField').value
alert(isValidLogin(username, password) ? 'Login successful' : 'Login failed')
}
// create a separate function for checking validity, so it's easier
// to refactor/reimplement later, if need be.
function isValidLogin(username, password) {
const usernameArray = ['name1', 'name2', ... 'nameN']
const passwordArray = ['pw1', 'pw2', ... 'pwN']
const usernameIndex = usernameArray.findIndex(item => item === username)
return usernameIndex !== -1 && passwordArray[usernameIndex] === password
}
let approvedLogins = ['JamesLiverton', 'SamW']
let approvedPasswords = ['password', 'coding']
function login(){
var username = document.getElementById('usernameField').value
var password = document.getElementById('passwordField').value
let index = approvedLogins.indexOf(username)
if (password === approvedPasswords[index]) {
alert('Login Sucessful')
} else {
alert('Login Unsucessful')
}
}
<input type="text" id="usernameField" placeholder="username" /><input type="text" id="passwordField" placeholder="password" />
<button onclick="login()">login</button>
Check this example:
var approvedLogins = ['JamesLiverton', 'SamW'];
var approvedPasswords = ['password', 'coding'];
function login(username) {
if (approvedLogins.includes(username)) {
var matchedPassword = approvedPasswords[approvedLogins.indexOf(username)];
console.log(matchedPassword);
} else {
console.log("Username not found in array!");
}
}
It checks if the Username provided in the login() parameter, is found in the array. If it's inside the array, then it gets the password relative to the position of the username within that array. For example, "SamW" would be "coding".
I hope this helps.

Angularfire Increment transaction

Im having trouble incrementing a count of post "likes". The following is what I have right now:
addLike(pid, uid) {
const data = {
uid: uid,
};
this.afs.doc('posts/' + pid + '/likes/' + uid).set(data)
.then(() => console.log('post ', pid, ' liked by user ', uid));
const totalLikes = {
count : 0
};
const likeRef = this.afs.collection('posts').doc(pid);
.query.ref.transaction((count => {
if (count === null) {
return count = 1;
} else {
return count + 1;
}
}))
}
this obviously throws and error.
My goal is to "like" a post and increment a "counter" in another location. Possibly as a field of each Pid?
What am I missing here? I'm certain my path is correct..
Thanks in advance
You're to use the Firebase Realtime Database API for transactions on Cloud Firestore. While both databases are part of Firebase, they are completely different, and you cannot use the API from one on the other.
To learn more about how to run transactions on Cloud Firestore, see updating data with transactions in the documentation.
It'll look something like this:
return db.runTransaction(function(transaction) {
// This code may get re-run multiple times if there are conflicts.
return transaction.get(likeRef).then(function(likeDoc) {
if (!likeDoc.exists) {
throw "Document does not exist!";
}
var newCount = (likeDoc.data().count || 0) + 1;
transaction.update(likeDoc, { count: newCount });
});
}).then(function() {
console.log("Transaction successfully committed!");
}).catch(function(error) {
console.log("Transaction failed: ", error);
});

I keep getting the error unexpected token b in JSON at position 0 at JSON.parse?

So I got this code that creates a html page.The function signup allows the user to register and create a password. The function checkpassword is to check if the correct password is entered for the username.It seems I have a problem in getting the item from local storage in my checkPassword function?Help will be much appreciated as I've been stuck for hours?
const PREFIX = "monash.eng1003.passwordApp.";
function checkPassword() {
var user = document.getElementById("registerUsername").value;
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var passwordToCheck = localStorage.getItem(PREFIX + user);
var passwordTwo = JSON.parse(passwordToCheck);
if (password != passwordTwo) {
alert("Don't hack" + user);
} else {
alert("Welcome" + user);
}
}
function signup() {
var user = document.getElementById("registerUsername").value;
var pass1 = document.getElementById("registerPassword").value;
var pass2 = document.getElementById("confirmPassword").value;
if ((pass1 === pass2) && (pass1 !== "")) {
if (localStorage) {
var passwordToStore = pass1;
localStorage.setItem(PREFIX + user, passwordToStore);
alert("Account created for username: " + user);
}
} else {
alert("Passwords must match and cannot be empty.")
}
}
EDIT:Thanks for pointing out that I do not need to parse it since I didn't stringify.That solved the problem but since I cannot delete the post I have to leave it here
You didn't convert the password to JSON when you stored it, so you don't need to use JSON.parse() when you retrieve it. You stored an ordinary string, you can just retrieve it and use it.
passwordTwo = localStorage.getItem(PREFIX + user);

Firebase data is not updated properly

The problem : the data always get updated into 4350,
And the alert keep's pop-up-ing.
The code:
// Get no antrian function
function getNoAntri(tipe, username, name) {
// Define firebase URL
var faskesRef = new Firebase("https://cepatsembuh.firebaseio.com/" + tipe + "/faskes/" + username);
// Log firebase URL
console.log('Url :' + "https://cepatsembuh.firebaseio.com/" + tipe + "/faskes/" + username);
// Warn user that this fiture need internet
alert('Fitur ini membutuhkan internet untuk mengambil data');
// Confirmation
alert("Mohon konfirmasi ulang");
var nama = prompt("Masukan nama"),
nik = prompt("Masukan NIK:");
if (nama != "" || nik.length != 16) {
var pasien = new Firebase("https://cepatsembuh.firebaseio.com/" + tipe + '/pasien/');
// Initialize data
faskesRef.on("value", function(snapshot) {
// Update variables
var data = snapshot.val().antrian,
one = 1,
sum = data + one;
// Update nomor antrian
faskesRef.update({
nama: name,
antrian: sum
});
// Print data
alert('No antrian: ' + snapshot.val().antrian);
// Push data to firebase
pasien.push().set({
nama: nama,
nomor_antrian: snapshot.val().antrian
})
});
} else {
// Error message
alert("Input anda tidak valid. \n Anda tidak bisa mendapatkan nomor antrian");
}
}
I've try many ways, but the code still never work.
Sorry If I doesn't ask a proper question btw
It's a bit unclear what your problem is, but an educated guess is that it boils down to this fragment of your code:
// Push input value to firebase
pasien.push().set({
nama: nama,
nik: nik,
lokasi: lokasi
});
window.location.href = 'option/' + 'available.html';
Writing data to Firebase is an asynchronous operation. Calling set() starts that operation, but by the time the set window.location, the write operation won't be done yet.
The solution is to wait for the write operation to complete before navigating away, which you can do by using a Firebase completion listener:
// Push input value to firebase
pasien.push().set({
nama: nama,
nik: nik,
lokasi: lokasi
}, function(error) {
if (!error) {
window.location.href = 'option/' + 'available.html';
}
else {
// TODO: handle error
}
});

SQLITE_ERROR: no such table in Node.js

I'm writing a simple server/client to keep track of the amount of times a user has logged in. A user can create an account and have their count set to 1. Following logins will increase their count in the backend SQLITE3 database.
In the example below, I run the "add" function which correctly checks if the user exists already, then if not, adds the username, password, and 1 to the table of users.
This properly returns 1 as you can see in the output, but why is it erroring at the end? I'm not making any other calls, but it's returning a no such table error. The only call I make is console.log(UsersModel.add('kpam', '123'));, which is on the last line of the code. I tried looking into the line 72 of events.js, but it didn't really give me much. I added print statements to make it trace more obvious, but I have a feeling something is going on behind the scenes?
Basically, I'm confused why if I only called one function, and that function returns successfully, theres an error at the end of execution?
Here is the error returned:
:$ node warmup.js
Creating DB file.
making table!
adding user!
1
events.js:72
throw er; // Unhandled 'error' event
^
Error: SQLITE_ERROR: no such table: Users
:$
And here is my code:
var http = require('http');
var fs = require('fs');
var file = 'data.db';
var exists = fs.existsSync(file);
if (!exists) {
console.log("Creating DB file.");
fs.openSync(file, 'w');
}
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(file);
var UsersModel = {
// success, no errors/problems
SUCCESS: 1,
// cannot find the user/password pair in the database (for 'login' only)
ERR_BAD_CREDENTIALS: -1,
// trying to add a user that already exists (for 'add' only)
ERR_USER_EXISTS: -2,
// invalid user name (empty or longer than MAX_USERNAME_LENGTH) (for 'add'/'login')
ERR_BAD_USERNAME: -3,
// invalid password name (longer than MAX_PASSWORD_LENGTH) (for 'add')
ERR_BAD_PASSWORD: -4,
// maximum user name length
MAX_USERNAME_LENGTH: 128,
// maximum password length
MAX_PASSWORD_LENGTH: 128,
login: function(user, password) {
if (!UsersModel.userExists(user, false)) {
return UsersModel.ERR_BAD_CREDENTIALS;
}
if (!UsersModel.checkPassword(user, password)) {
return UsersModel.ERR_BAD_CREDENTIALS;
}
count = UsersModel.increaseCount(user);
return count;
},
add: function(user, password) {
if (UsersModel.userExists(user, true)) {
return UsersModel.ERR_USER_EXISTS;
}
if (!UsersModel.isValidUsername(user)) {
return UsersModel.ERR_BAD_USERNAME;
}
if (!UsersModel.isValidPassword(password)) {
return UsersModel.ERR_BAD_PASSWORD;
}
UsersModel.addUser(user, password);
return 1;
},
userExists: function(user, makeTable) {
if (!exists) {
if (makeTable) {
console.log('making table!');
db.run('CREATE TABLE Users (name TEXT, password TEXT, count INT)');
}
return false;
}
db.serialize(function() {
console.log('checking user!');
row = db.get("SELECT name FROM Users WHERE name = '" + user + "'");
});
return !(typeof(row.name) === 'undefined');
},
increaseCount: function(user) {
db.serialize(function() {
console.log('increasing count!');
count = db.get("SELECT count FROM Users WHERE name = '" + user + "'") + 1;
db.run("UPDATE Users SET count = '" + count + "' WHERE name = '" + user + "'");
return count;
});
},
addUser: function(user, password) {
count = 0;
console.log('adding user!');
db.run("INSERT INTO Users (name, password, count) VALUES ('" + user + "','" + password + "','" + 0 + "')");
},
checkPassword: function(user, password) {
db.serialize(function() {
console.log('checking pw!');
row = db.get("SELECT password FROM Users WHERE name = '" + user + "'");
});
return row.password == password;
},
isValidUsername: function(user) {
return user.length < 129;
},
isValidPassword: function(password) {
return password.length < 129;
}
}
console.log(UsersModel.add('kpam', '123'));
The db.run(...) calls are asynchronous. So they return immediately, and look like success to your code. However they're still running in the background. Because of this, the SELECT statement is likely starting to run before the CREATE TABLE completes. And that's why you get that error.
I notice that the SELECT statement is inside of a db.serialize(...) call. Unfortunately, that call only serializes statements that are directly inside its scope. All calls outside of the serialize block continue to run in parallel (this includes the INSERT statement that comes up later).
Your code needs to be restructured to use the callbacks that the node sqlite3 module relies on. Take a look at the simple example at:
https://github.com/mapbox/node-sqlite3/blob/master/examples/simple-chaining.js
Notice how the last parameter to each db operation is the name of the function to call after the operation is completed.

Categories