Ionic + Javascript: How to create promise with Firebase - javascript

I have the simple function of doRegisterUser() which basically uses a function defined in a provider to check if username already registered or not. In the following code, I print to console, call provider's function and then print to console. Simply I am doing this just to observe the sequence of execution. What I want is to have checkUsernameReserved() execute and then any the console print to happen.
How can this be accomplished?
doRegisterUser() {
var self = this;
/*Step A - Check username provided by user is taken or not. If no username taken, create random username*/
console.log("Before checkUsernameReserved() execution");
self.firebaseProvider.checkUsernameReserved(self.username);
console.log("After checkUsernameReserved() execution");
}
and this is the provider function which uses the firebase:
checkUsernameReserved(username:string): any{
/*Check usernamesTaken table for provided username*/
firebase.database().ref('/usernames_taken/' + username).once('value').then(function(snapshot) {
/*Check if username is taken.*/
if(snapshot.val() != null && snapshot.val() != "")
{
console.log("Username Taken");
}else{
console.log("Username Available");
}
})
}
The current output I am getting in console is:
Before checkUsernameReserved() execution
After checkUsernameReserved() execution
Username Taken

Two things:
Return your promise from checkUsernameReserved
Put code that must run after the check in the .then of that promise.
So:
doRegisterUser() {
var self = this;
/*Step A - Check username provided by user is taken or not. If no username taken, create random username*/
console.log("Before checkUsernameReserved() execution");
self.firebaseProvider.checkUsernameReserved(self.username).then(() => {
// Put code that must run after the check in here...
console.log("After checkUsernameReserved() execution");
});
}
checkUsernameReserved(username:string): any{
/*Check usernamesTaken table for provided username*/
// !! note the return !!
return firebase.database().ref('/usernames_taken/' + username).once('value').then(function(snapshot) {
/*Check if username is taken.*/
if(snapshot.val() != null && snapshot.val() != "") {
console.log("Username Taken");
} else {
console.log("Username Available");
}
});
}

Related

How to check if user is undefined

I have a command that sends a DM to user and the user is defined like this:
let user;
if (message.mentions.users.first()) {
user = message.mentions.users.first();
} else if (args[0]) {
user = message.guild.members.cache.get(args[0]).user;
}
But if I ping a user that is not in this server or write something that is not #user, it sends an error "user is not defined". I tried making if (user == "undefined"), but it just aborts before it reaches it or if I put it above it can't work.
Instead of looking for the members with message.guild.members and then get the user from there, you could get the client.users and check if a user with the args[0] ID exists. If it doesn't exist, you can simply check if (!user) you don't have to check if it's undefined.
const user = message.mentions.users.first() || message.client.users.cache.get(args[0]);
if (!user)
return message.channel.send('There is no user mentioned');
message.channel.send(`You mentioned ${user}`);
You can also use fetch() to get the user instead of relying on cache:
let user;
try {
user = message.mentions.users.first() || (await message.client.users.fetch(args[0]));
} catch (error) { console.log(error); }
if (!user)
return message.channel.send('There is no user mentioned');
message.channel.send(`You mentioned ${user}`);
You are currently checking if you have written user as "undefined" when actually you want to see if the user is undefined.
Another issue with your code is that args[0] will return the command name when you want the next argument over from that, args[1].
Full example:
let user;
if (message.mentions.users.first()) {
user = message.mentions.users.first();
} else if (args[0]) {
user = message.guild.members.fetch(args[1]).user;
} else {
return message.channel.send("Please provide a user"); //Sends if the message author did not provide a user
}
if (user == undefined) return message.chanel.send("I could not find the user you are looking for"); //Sends if the user is not in the current guild or doesn't exist
For each variable in javascript you can take its type and obviously if its type is === 'undefined' then it is undefined.
if(typeof comment === 'undefined') {
alert('Variable "comment" is undefined.');
}

Firebase - change remember property dynamically when authenticating

I have a checkbox input in my html which the user can check if he/she wishes to stay logged into the app after the browser has been closed. I would like to change between remember: "default", and remember: "sessionOnly" depending on whether the user checks the box or not.
This is my function to check whether the box in the html is checked or not:
function checkLoginTerm() {
var result;
if(document.getElementById('#loginkeeping').checked) {
result = "sessionOnly";
} else {
result = "default";
}
return result;
}
Then I call the function in my login function to be executed after the user authenticates like this:
function loginUser(username, password) {
if (checkVariable(username)) {var username = document.getElementById("loginUsername").value;}
if (checkVariable(password)) {var password = document.getElementById("loginPassword").value;}
firebaseRef.authWithPassword({
email : username,
password : password
}, function(error, authData) {
if (error) {
alert("Login Failed! "+ error, error);
} else {
console.log("Authenticated successfully with payload:", authData);
}
}, {
remember: checkLoginTerm()
});
}
If I do this, the login process will never complete. But if I put the appropriate string directly after remember: (for example remember: "sessionOnly"), it will do what its told.
As pointed out by Rob DiMarco in the comments below my question, there were two minor issues -
The id of the element is loginkeeping and not #loginkeeping
I had made a logic error in the conditional statement within my checkLoginTerm() function

Firebase custom login fails (JavaScript)

I'm trying to get started with firebase and now with the security part of it. I'm trying to keep it as simple as possible in order to get started, using guides and code snippets from the Firebase website.
In order to keep it simple I have a webpage containing a password (id "Code") and user input field (id "Door"). How do I check if the password entered in field "Code" is equal to the password that is already stored in node https://mydatabase.firebaseio.com/loapp_users/BAAJ/password, BAAJ being a userid of one of the users stored in node loapp_users, all with a child node "password"?
The code below doesn't seem to do the trick.
$(document).ready(function(){
// Monitoring User Authentication State
// Use the onAuth() method to listen for changes in user authentication state
// Create a callback which logs the current auth state
function authDataCallback(authData) {
if (authData) {
console.log("User " + authData.uid + " is logged in with " + authData.provider);
} else {
console.log("User is logged out");
}
}
// Register the callback to be fired every time auth state changes
var ref = new Firebase("https://mydatabase.firebaseio.com");
ref.onAuth(authDataCallback);
$("#logout").click(
function logout() {
ref.unauth();
ref.offAuth(authDataCallback);
}
);
// LOGIN
// The code to authenticate a user varies by provider and transport method, but they all have similar signatures and
// accept a callback function. Use it to handle errors and process the results of a successful login.
// Create a callback to handle the result of the authentication
function authHandler(error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
console.log("Authenticated successfully with payload:", authData);
}
};
$("#login").click(
function() {
var usersRef = new Firebase("https://mydatabase.firebaseio.com/loapp_users");
// Authenticate users with a custom Firebase token
var _user = $("#Door").val();
var _level = "docent";
var _password = $("#Code").val();
var userRef = usersRef.child(_user);
// Attach an asynchronous callback to read the data at our user reference
userRef.on("value", function(snapshot) {
console.log(snapshot.val());
if (snapshot.val().child("password").text() == _password) {
ref.authWithCustomToken("eyJ0e....etc...mlhdCI6MTQyOTM4Mzc0M30.Vn1QF7cRC6nml8HB9NAzpQXJgq5lDrAie-zIHxtOmFk", authHandler);
} else {
console.log("Gebruikersnaam en code komen niet overeen")
}
}, function (errorObject) {
console.log("The read failed: " + errorObject.code);
});
}
);
});
snapshot.val().child("password").text()
should instead be:
snaphot.val().password
Then it works.

looping the local storage

I want to loop the local storage for the password and username to check if correct and alert a message if or if not.
The code is working well, but I don't know where to write the "invalid username" message because the loop goes through every record, so the messages pops ups for every record check until it finds it.
What I want is to pop up the message when the search is done.
Here is my code:
$("#login").click(function(){
var username =$("#user").val();
var password =$("#pass").val();
var userCount = localStorage.getItem('userCount');
for (i=1;i<=userCount;i++) {
var user = JSON.parse(localStorage.getItem("user" + i));
if((user.username == username)||(user.password == password)){
alert("welcome "+username);
} else {
alert("Invalid Username");//this message keeps poping up on every record until username found
}
}
});
Put the loop inside a function.
Return true (or the user object) from that function if anything inside the loop matched.
Return false after the loop (which you'll only reach if nothing matches).
Handle your alert outside the function based on the return value of calling it.
Set a boolean variable to true when you find a match, and stop the loop using break. Otherwise, if the boolean is still false after the loop completes, no match was found.
$("#login").click(function(){
var username =$("#user").val();
var password =$("#pass").val();
var userCount = localStorage.getItem('userCount');
var foundOne = false;
for (i=1;i<=userCount;i++) {
var user = JSON.parse(localStorage.getItem("user" + i));
if((user.username == username)&&(user.password == password)){
foundOne = true;
break;
}
}
if(foundOne) {
alert("welcome "+username);
// other "welcome" code
} else {
alert("Invalid Username");
}
});
NB, you may want to use the && operator instead of || here:
(user.username == username)&&(user.password == password)
otherwise you may get a match for one user who has the same password as another.

Serial Promises and Response.Success in Cloud Code

I'm a little confused about where to place a response.success() when using serial Promises.
Here's the situation: I've got a cloud function that accepts an array of email addresses and the current user. The function does the following:
Finds the current user based upon it's user object id.
Iterates over the array of emails addresses
Find if there is an existing user for each given email address
If there is an existing user, we check to see if the existing user and the current user are friends
If they are not friends, it creates a friendship.
Now when I run this function without a response.success(), it does exactly what I expect it to and the friendships entries are created. But no matter where I place the response in the code, I get the resulting response.success message and none of the serialized promises execute.
Why the resulting success/failure matters: I'm executing this function from an iOS app and I'd like to properly handle the success or failure cases correctly on the iOS side.
Here is the cloud function:
Parse.Cloud.define("friendExistingUsers", function(request, response) {
// Get our parameters
var addresses = request.params.emailAddresses;
var userId = request.params.user;
// Query for our user
var userQuery = new Parse.Query("User");
userQuery.equalTo("objectId", userId)
userQuery.first().then(function(currentUser) {
// if we find the user, walk the addresses
var promise = Parse.Promise.as("success");
_.each(addresses, function(address) {
console.log(address);
// add a then to our promise to handle whether a relationship is
// being created.
promise = promise.then(function() {
// find if there is a user for that address
var emailQuery = new Parse.Query("User");
emailQuery.equalTo("email", address);
emailQuery.first().then(function(addressUser) {
if (typeof addressUser != 'undefined') {
// found one.
console.log(addressUser);
// figure out if our current user and this user are
// friends.
var friendQuery = new Parse.Query("FVFriendship");
friendQuery.equalTo("from", currentUser);
friendQuery.equalTo("to", addressUser);
friendQuery.first().then(function(relationship) {
if (typeof relationship != 'undefined') {
// if they are, we need to pass.
console.log("Found a relationship: " = relationship)
} else {
// They are not. Add the friendship
var Friendship = Parse.Object.extend("FVFriendship");
var friendship = new Friendship();
friendship.set("from", currentUser);
friendship.set("to", addressUser);
friendship.save().then(function(result) {
console.log("Created a friendship: " + result)
});
};
});
} else {
// we did not find a user for that address
console.log("No user for " + address);
};
});
});
});
console.log(promise);
return promise;
}).then(function() {
response.success("success");
});
});
Thanks in Advance. Let me know if there's anything else I can add.
Your .then callback function attached to promise should return a promise. Missing this is a common mistake when using promises.
Also Parse doesn't seem to show objects with console.log as browsers do, so I wrap them into JSON.stringify().

Categories