Why doesn't my Google authentication work in Firebase? - javascript

I've modeled my Google logon after the example provided by Firebase at http://jsfiddle.net/firebase/a221m6pb/
However when I run my code (https://firetest-wadeziegler.c9.io/logon) the popup goes blank after selecting user and never closes. The callback code is never executed. Any ideas why this isn't working?
Authorized Domains for OAuth Redirects:
firetest-wadeziegler.c9.io
logon.js
function logonWithGoogle() {
var promise = session.logonWithGoogle();
$.when(promise)
.then(function (authData) {
setTimeout(function() { window.location.replace('/') }, 0);
}, function (error) {
showMessageBox('Logon Failed', error);
});
}
session.js
var session = new Session();
function Session() {
this.firebase = new Firebase("https://glowing-inferno-3026.firebaseio.com");
this.firebase.onAuth(function globalOnAuth(authData) { } );
}
Session.prototype.isLoggedOn = function() {
return this.firebase.getAuth() != null;
}
// Returns Promise object
Session.prototype.logonWithGoogle = function() {
var deferred = $.Deferred();
this.firebase.authWithOAuthPopup("google",
function (err, user) {
if (err) {
deferred.reject(err);
}
if (user) {
deferred.resolve(user);
}
}
, {
remember: "sessionOnly",
scope: "email,profile"
});
return deferred.promise();
}

The problem was with the calling code and the lack of a preventDefault() on the click within a form. The page reloaded right after the click but it was so quick I didn't notice. Stupid mistake.
<button onClick="logonWithGoogle(); return false /* prevent submit */">

Related

How to launch a method on all ng-click events AngularJS

I have made a web application in Node.js that lets users manage their mongoDB database. I have several click events that do CRUD actions that change the status of the database. On each ng-click I call the corresponding function to do the CRUD action. The problem is that, in each of these functions I call the a method called refresh which updates the page so it matches the current database info. Is there a way, I can just hook up the refresh function to be called whenever a ng-click event has ended?
Examples
$scope.dropDB = function (DB) {
$http.post('/dropDB', JSON.stringify({ 'DB': DB })).success(function (response) {
refresh();
});
};
$scope.addDB = function (DB) {
try{
var objson = JSON.stringify({ 'DB': DB }) ;
$http.post('/addDB', objson).success(function (response) {
console.log("DB Added: ");
refresh();
});
}catch(ex){
alert("Not a valid input type");
}
};
Make wrapper factory for your http call
['$http', function($http) {
return function(method, route, body) {
var args = method === 'POST' ? [route, body] : [route];
return new Promise(function(resolve, reject) {
return $http[method].apply(this, args).then(function(res) {
refresh();
resolve(res)
}).catch(function(err) {
reject(err);
})
});
}
}];
Then you can use it in your controller
myFactory('POST', '/database', {foo: 'bar'}).then(function(res) {
// at this point refresh() was already called
})

Recursive Promise Call- Memory Scope Variable Issue

I have these functions for the purpose of retrieving a token through a api call out. If the user enters the wrong password, the promise will reject and on reject the function is called again to give the user another try.
If the user enters the right password the first time, there is no issue.
But if the user enters a wrong password and tries again...but tries again successfully, I am having a memory issue. Because of the recursive call to callApiToken() on the second try the promise is fullfilled and callApiToken().then(function() { refreshToken(); }) is called. file.token = JSON.parse(tokenString); is completed but in a different memory scope. Not sure what to do about this. I say this because the routine runs successfully. But the global var file is not populated as it should be.
createTokenFile() is called first.
var file = {};
function createTokenFile() {
block = true;
callApiToken()
.then(function() { refreshToken(); }) // ON THE SECOND RECURSIVE
.catch(function() { // RUN refreshToken() IS CALLED
callApiToken();
}).finally(function() {
block = false;
});
}
function refreshToken() {
var tokenFileAbsolute = path.join(__dirname, 'token-file.json');
return fs.readFileAsync(tokenFileAbsolute, {encoding: 'utf-8'})
.then(function(tokenString) {
file.token = JSON.parse(tokenString);
}).catch(function(err) {
console.log("No token-file.json file found. " .red +
"Please complete for a new one." .red);
createTokenFile();
});
}
UPDATE with other promise code that gives resolve for callApiToken()which is actually getCredentials:
Note: fs.writeFileAsync(tokenFile, token) does complete successfully on the second recursive call.
function getPassword(user) {
return readAsync({prompt: "Password: ", silent: true, replace: "*" })
.then(function(pass) {
return postAsync(URL, payload(user[0], pass[0]));
});
}
function getCredentials() {
return readAsync({prompt: "Username: "}).then(getPassword);
}
function writeToFile(data, response) {
tokenFile = path.join(__dirname, 'token-file.json');
token = JSON.stringify({
id: data.access.token.id,
expires: data.access.token.expires
});
return fs.writeFileAsync(tokenFile, token).then(function(err) {
if (err) throw err;
console.log("Token was successfully retrieved and written to " .cyan +
tokenFile .cyan + "." .cyan);
});
}
There is no such thing as a "memory scope". You simply have a timing issue!
If an action is asynchronous, you always have to return a promise from the function when you want to wait for the result - and you seem to do.
var file = {};
function createTokenFile() {
block = true;
callApiToken()
.then(function() {
return refreshToken();
// ^^^^^^ here
})
.catch(function() {
return callApiToken();
// ^^^^^^ and here
}).finally(function() {
block = false;
});
}
function refreshToken() {
var tokenFileAbsolute = path.join(__dirname, 'token-file.json');
return fs.readFileAsync(tokenFileAbsolute, {encoding: 'utf-8'})
.then(function(tokenString) {
file.token = JSON.parse(tokenString);
}).catch(function(err) {
console.log("No token-file.json file found. " .red +
"Please complete for a new one." .red);
return createTokenFile();
// ^^^^^^ and here!!!
});
}
Btw, my guess is that your recursion is flawed. Don't you want refreshToken to reject, and createTokenFile to call itself from within itself (instead of the second callApiToken())?

Why can I get a Bluebird catch in the middle of chain stop the rest of the chain execution

I am building this promise chain. The goal is to have the first action check for uniqueness on a field in the DB, and then if unique, save the object. But if the object is not unique, it should not save, and should return an error response.
function(request, reply) {
var payload = request.payload;
checkThatEmailDoesNotExist().then(saveUser)
function checkThatEmailDoesNotExist() {
return User.where({email: payload.email}).countAsync()
.then(function(count) {
if (count > 0) {
throw Boom.badRequest('The email provided for this user already exists')
}
return null;
})
.catch(function(err) { // ~This catch should stop the promise chain~
reply(err);
})
}
function saveUser() {
// ~But instead it is continuing on to this step~
return User.massAssign(request.payload).saveAsync()
.spread(function(user, numAffected) {
return reply(user);
})
.catch(function(err) {
server.log(['error', 'api', 'auth'], err);
throw Boom.badRequest('Object could not be saved to database');
});
}
}
If an error is thrown in the checkThatEmailDoesNotExist() it's catch() should return the error, and stop processing the rest of the original promise chain.
Instead of acting that way, the catch() fires, and then continues to move on to the saveUser() function.
You are mixing promises and callbacks which is a horrible anti-pattern. The caller will simply use
the returned promise, there is no need to manually wire things back to callbacks.
function save(request) {
var payload = request.payload;
return User.where({email: payload.email}).countAsync()
.then(function(count) {
if (count > 0) {
throw Boom.badRequest('The email provided for this user already exists')
}
return User.massAssign(request.payload).saveAsync()
})
.get(0)
/* equivalent to
.spread(function(user, numAffected) {
return user;
}) */
.catch(Promise.OperationalError, function(err) {
server.log(['error', 'api', 'auth'], err);
throw Boom.badRequest('Object could not be saved to database');
});
}
Usage:
save(request).then(function(user) {
response.render(...)
}).catch(function(e) {
response.error(...)
})
If you wanted to expose a callback api, the sane way to do that is to bolt on a nodeify at the end of an existing promise api and call it a day:
function save(request, callback) {
var payload = request.payload;
return User.where({email: payload.email}).countAsync()
.then(function(count) {
if (count > 0) {
throw Boom.badRequest('The email provided for this user already exists')
}
return User.massAssign(request.payload).saveAsync()
})
.get(0)
/* equivalent to
.spread(function(user, numAffected) {
return user;
}) */
.catch(Promise.OperationalError, function(err) {
server.log(['error', 'api', 'auth'], err);
throw Boom.badRequest('Object could not be saved to database');
})
.nodeify(callback);
}
save(request, function(err, user) {
if (err) return response.error(...);
response.render(...);
});

What's the best way to get a function return to wait until an asynchronous operation has finished?

Given the following prototype function:
Client.prototype.getLocalIp = function() {
var rtc = new window.RTCPeerConnection({iceServers: []});
rtc.createDataChannel('', {reliable: false});
var that = this;
rtc.onicecandidate = function(event) {
if (event.candidate) {
that.localIp = grep(event.candidate.candidate);
}
};
rtc.createOffer(function (offer) {
that.localIp = grep(offer.sdp);
rtc.setLocalDescription(offer);
}, function (error) {
console.warn('Fetching local IP failed', error);
});
var grep = function(sdpOrCandidate) {
// Does lots of string processing stuff and returns a string
}
console.log("Returning from function");
console.log(this.localIp);
}
How can I stop the function from returning until the grep function has finished doing its business and returned a value? Here's a JSFiddle demonstrating what I mean: http://jsfiddle.net/tjkxcL1j/
If you look in your browser console you should see that the getLocalIp() function is returning null first until the async stuff from rtc.onicecandidate and/or rtc.createOffer is finished.
Your function needs to accept a callback argument
Client.prototype.getLocalIp = function getLocalIp(done) {
// ...
rtc.createOffer(function (offer) {
that.localIp = grep(offer.sdp);
rtc.setLocalDescription(offer);
// call the callback here
done(null, that.localIp);
},
function (error) {
console.warn('Fetching local IP failed', error);
// call the callback with an error here
done(error);
});
};
Then you can use it like this
client.getLocalIp(function(err, ip){
if (err) return console.error(err.message);
console.log("client ip", ip);
});
However, as #zerkms mentions in a comment, this is only going to work if actually async operations are happening. Examples include accessing information over a network or accessing the disk.

Chaining multiple promises (handling callbacks)

I am having some difficulties with promises when it comes chaining multiple ones. The confusion is distinguishing how to properly take advantage of promises & their difference with Callbacks. I noticed that callbacks sometime fire regardless a promise is resolved or not, making the below implementation unreliable..(Unless my syntax & logic are wrong) I read the official documentation and came up with this, but I am not sure it is well implemented.The Registration flow is as follow:
User chooses an Alias -> Details Alias + userID (Device's Universally Unique Identifier) are sent server side
If Alias is available, ApiKey(token) is generated, User registered and sent back client side (Stored in DB)
Services.js
(function(angular) {
myApp.factory("deviceDB.Service", ['$resource', '$http', '$q',
function ($resource, $http , $q ) {
return {
//Second Promsie : After API token is generated server-side, store res in db
RegDevice: function (alias, apiKey, userID) {
var deferred = $q.defer();
var configuration ;
var db = window.sqlitePlugin.openDatabase({name: "config.db"});
setTimeout(function () {
db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS user_details (userID UNIQUE , alias TEXT, apiKey TEXT)');
tx.executeSql("INSERT INTO user_details (userID, alias, apiKey) VALUES (?,?,?)", [userID, alias, apiKey], function (tx, res) {
deferred.resolve(configuration = true);
}, function (e) {
// console.log("ERROR: " + e.message);
deferred.reject(configuration = false);
});
});
}, 1000);
return deferred.promise;
},
//First Promsie: Register user server side & generate APi token
RegUser: function (alias, userID) {
var deferred = $q.defer();
var pro;
pro = $resource('api/query/register', {'alias': alias, 'userID': userID},
{ query: {
isArray: false,
method: 'GET' } });
setTimeout(function () {
pro.query(function (res) {
if (res.error) {
deferred.reject( { error : res.error, exists: res.exists, msg: res.message } );
}
else {
deferred.resolve( {error : res.error , alias: res.alias , apiKey: res.apiKey, msg: res.message } );
}
}, function (e) {
deferred.reject( { errorStatus: e.status } );
});
}, 1000);
return deferred.promise;
}
};
}]);
}(window.angular));
Now, in My controller I would like to chain both promises above. I quote the follwoing from the Documentation :
then(successCallback, errorCallback, notifyCallback) – regardless of when the promise was or will be resolved or rejected, then calls one of the success or error callbacks asynchronously as soon as the result is available. The callbacks are called with a single argument: the result or rejection reason. Additionally, the notify callback may be called zero or more times to provide a progress indication, before the promise is resolved or rejected.
What is the point of having Callbacks if they can fire regardless if the Promise is resolved?
Shouldn't I call for e.g Promise2 within the first Promise's Success Callback? If it is fired regardless of of Promise1 being resolved, How then can I chain Promise2 in a way to fire only when Promise1 is resolved?
What I tried :
Controller.js
myApp.controller('RegisterController', ['$scope', '$http', 'deviceDB.Service',
function ($scope , $http , deviceDB.Service) {
var Promise1 = deviceDB.RegUser($scope.alias, $scope.Device);
// First promise - Validate with server
Promise1.then(function(data)
{
console.log(' Registration Server-Side successfully');
$scope.apiKey = data.apiKey;
term.echo(data.apiKey);
}, function(e)
{
console.log('Registration Failed');
term.echo(e.msg);
})
//Call Promise 2 & Store details Client-Side using .then()
.then(deviceDB.RegDevice($scope.alias, $scope.apiKey, $scope.Device),
function(d){
console.log('Items Stored in DB successfully');
}, function()
{
console.log('Items Stored in DB Failed');
});
}]);
Notes: I understand it is a bad practice to store details client-side, however, i am after a different concept (anonymous messaging) and there is no security concerns..
Thanks for your time
Your second then call seems incorrect, after
//Call Promise 2 & Store details Client-Side using .then()
then takes up-to 3 parameters then(successCallback, errorCallback, notifyCallback) you are passing it: deviceDB.RegDevice($scope.alias, $scope.apiKey, $scope.Device) which is evaluated immediately and the promise returned is passed to the function then as the success function, your success function is passed as the errorCallback and your fail function is passed as the notifyCallback.
I would try the following
Promise1.then(function(data)
{
console.log(' Registration Server-Side successfully');
$scope.apiKey = data.apiKey;
term.echo(data.apiKey);
return deviceDB.RegDevice($scope.alias, $scope.apiKey, $scope.Device)
}, function(e)
{
console.log('Registration Failed');
term.echo(e.msg);
return e;
}).then(function(d) {/*all good*/}, function(e) {/* all bad */}
Notice the call to RegDevice is now within a function block, and a promise is returned from the then block you want to chain from.
I find $q.serial a great library for chaining promises. It's very easy to use and handles a lot of stuff like checking if all promises on the chain are really promises.
Here is a small example:
function do_all() {
var task_1 = function() {
return $http.get("some url")
.then(on_xhr_completed_fn, on_xhr_failed_fn);
}
var task_2 = function(some_data) {
vm.bla = some_data;
return $http.get("other url")
.then(on_xhr_completed_fn, on_xhr_failed_fn);
}
var task_3 = function(other_data) {
vm.bli = other_data;
}
var tasks = [task_1, task_2, task_3];
return $q.serial(tasks)
.then(function() {
console.log("Finished tasks 1, 2 and 3!!!");
});
}
Here's an approach that may be helpful using async/await:
async function run_promise_A(args) {
return new Promise((resolve, reject) => {
return resolve(resolve_value)
});
}
async function run_promise_B(args) {
return new Promise((resolve, reject) => {
return resolve(resolve_value)
});
}
async function run_promise_C(args) {
return new Promise((resolve, reject) => {
return resolve(resolve_value)
});
}
async function run_several_async_functions(userid) {
let a = run_promise_A(userid);
let b = run_promise_B(a);
let c = run_promise_C(b);
return c;
}
return Promise.resolve()
.then(() => {
let c = (async () => {
let c = await run_several_async_functions(userid)
return c;
})();
return c;
})
.then((c) => {
return c;
})
.catch((err) => {
console.log(err);
});

Categories

Resources