How to display ionic2 Alert after Firebase changeEmail - firebase

I have the following function to change the email on a Firebase user account. I want to display an ionic2 alert when complete, whether it was successful or there was an error. From my code below I do get the alert to display BUT it is blank. Most likely it is a timing issue on the Firebase promise but I don't know how to fix it.
private doChangeEmail(data): void {
var myAlert: {
title?: string,
subtitle?: string
} = {};
this.auth.ref.changeEmail({
oldEmail: data.oldemail,
newEmail: data.newemail,
password: data.password
}, function(error) {
if (error) {
switch (error.code) {
case "INVALID_PASSWORD":
myAlert.title = 'Invalid Password';
myAlert.subtitle = 'The specified user account password is incorrect.';
break;
case "INVALID_USER":
myAlert.title = 'Invalid User';
myAlert.subtitle = 'The specified user account does not exist.';
break;
default:
myAlert.title = 'Error creating user';
myAlert.subtitle = error;
}
} else {
myAlert.title = 'DONE';
myAlert.subtitle = 'User email changed successfully!';
}
});
let alert = Alert.create({
title: myAlert.title,
subTitle: myAlert.subtitle,
buttons: [{
text: 'OK',
handler: () => {
}
}]
});
this.nav.present(alert);
}

put the alert code inside the promise result....
this.auth.ref.changeEmail({
oldEmail: data.oldemail,
newEmail: data.newemail,
password: data.password
}, function(error) {
if (error){
// do error stuff..
} else {
// do success stuff..
}
// show alert here...
})

I found the following comment by Frank van Puffelen which solved my issue:
You're using this inside a callback function, where it has a different meaning. One solution is to use fat-arrow/rocket notation for the callback, which ensures this is what you expect it to be:
The correct syntax should be
this.auth.ref.changeEmail({
oldEmail: data.oldemail,
newEmail: data.newemail,
password: data.password
}, (error) => {
if (error){
// do error stuff..
} else {
// do success stuff..
}
// show alert here...
})
and the alert shows correclty as pointed out by Aaron Saunders

Related

Firebase Phone Auth Error 400

Just getting started with Firebase phone auth. Seems pretty slick however I've hit a wall with a bug.
{
"error": {
"errors": [
{
"domain": "global",
"reason": "invalid",
"message": "SESSION_EXPIRED"
}
],
"code": 400,
"message": "SESSION_EXPIRED"
}
}
Starting with the Captcha: (standard documentation code!)
var applicationVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
'size': 'invisible',
'callback': function(response) {
},
'expired-callback': function() {
}
});
Its rendered and the captcha works well.
Next is the sign-in bit where you are sent the auth code to your phone. Works great:
$scope.signInWithPhoneNumber = function signInWithPhoneNumber() {
var phoneNumber = "*censored*";
var appVerifier = window.recaptchaVerifier;
firebase.auth().signInWithPhoneNumber(phoneNumber, applicationVerifier)
.then(function (confirmationResult) {
// SMS sent. Prompt user to type the code from the message, then sign the
// user in with confirmationResult.confirm(code).
window.confirmationResult = confirmationResult;
$scope.setConfirmationResult(confirmationResult);
alert('Result: ' + JSON.stringify(confirmationResult));
}).catch(function (error) {
// Error; SMS not sent
alert('Error: ' + error);
// ...
});
};
Finally its the authentication of the code that the user inputs from the text message. Here is when I get the error 400:
$scope.AuthenticateCode = function (code) {
var code = String(document.getElementById("auth_code").value);
var confirmationResult = $scope.getConfirmationResult();
alert(code);
confirmationResult.confirm(code).then(function (result) {
// User signed in successfully.
var user = result.user;
console.log('Signed In! ' + JSON.stringify(user));
// ...
}).catch(function (error) {
// User couldn't sign in (bad verification code?)
// ...
});
}//end of AuthenticateCode
The error is coming from the VerifyPhone method:
https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPhoneNumber?key=censored
Any help or ideas?
Many Thanks,
Kieran
Ok, there are 2 likely reasons:
The code expired. The user took too long to provide the SMS code and finish sign in.
The code was already successfully used. I think this is the likely reason. You need to get a new verificationId in that case. Get a new reCAPTCHA token via the invisible reCAPTCHA you are using.
You are most likely to forget the "Country Code" before the phone no.
That is why firebase throw error 400 which means invalid parameters
If it's an Ionic3 project, change the following lines:
Imports:
import { AngularFireAuth } from 'angularfire2/auth';
import firebase from 'firebase';
Create var:
public recaptchaVerifier: firebase.auth.RecaptchaVerifier;
on "ionViewDidLoad()"
this.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
on "your_method(phoneNumber: number)"
const appVerifier = this.recaptchaVerifier;
const phoneNumberString = "+" + phoneNumber;
this.fireAuth.auth.signInWithPhoneNumber(phoneNumberString, appVerifier)
.then(confirmationResult => {
// SMS sent. Prompt user to type the code from the message, then sign the
// user in with confirmationResult.confirm(code).
let prompt = this.alertCtrl.create({
title: 'Enter the Confirmation code',
inputs: [{ name: 'confirmationCode', placeholder: 'Confirmation Code' }],
buttons: [
{
text: 'Cancel',
handler: data => { console.log('Cancel clicked'); }
},
{
text: 'Send',
handler: data => {
confirmationResult.confirm(data.confirmationCode)
.then(result => {
// Phone number confirmed
}).catch(error => {
// Invalid
console.log(error);
});
}
}
]
});
prompt.present();
})
.catch(error => {
console.error("SMS not sent", error);
});
Reference:
Firebase Phone Number Authentication
I got into a similar situation when a POST request to google API was returning Bad Request 400. When the message was logged, it said:
All requests from this device are blocked due to Unusual Activity. Please try again later
The issue was when the ReCaptcha was sensing a bot out of my development environment and it worked well when I tried later. During the rest of the development, I turned off this feature for easy work.

Can't catch meteor error thrown in Method from Event

I have a method and it throws an error so I can catch it in my event and display it to the user, like this:
Meteor.methods({
addPlayer: function(nickname) {
if (nickname == "") {
throw new Meteor.Error('empty-nickname', 'You must choose a nickname');
} else {
Player.insert({
nickname: nickname,
});
}
},
})
and in my event
'submit form': function (e) {
e.preventDefault();
var nickname = $('input').val();
Meteor.call('addPlayer', nickname, function(error, result) {
if (error) {
console.log(typeof error);
console.log(error);
}
});
}
However, meteor still throws an Exception while simulating the effect of invoking 'addPlayer', and the error variable is not an error object, but a string with the same message as the console log, so I get two errors in my console instead of an error object.
Wrapping method.call in a try/catch does not work.
What am I missing here?
-- Edit
Here is an print screen of the result:
Image link for full resolution: http://i.stack.imgur.com/zABar.png
Throw the error only on the server. Wrap it inside if(!this.isSimulation) {}
Meteor.methods({
addPlayer: function(nickname) {
if (nickname == "") {
if(!this.isSimulation) {
throw new Meteor.Error('empty-nickname', 'You must choose a nickname');
}
} else {
Player.insert({
nickname: nickname,
});
}
},
})

firebase executing method twice

I have set up a firebase simple login and its all working within my angular project. However for soem reason when ever I call the functions I have set up containing the login and createUser methods, they are called twice?
The controller is set up as follows:
angular.module('webApp')
.controller('AccountCtrl', function($scope, $window, $timeout) {
var ref = new Firebase('https://sizzling-fire-4246.firebaseio.com/');
and both methods are placed within my function straight from the firebase example on their website
When I press register, it will create the user and authenticate it, and then it will run again and tell me the email is taken.
I have checked with and without the timeouts and it still happens.
$scope.login = function(){
$scope.loginErrors = [];
$scope.loginSuccess = '';
var user = $scope.loginUser;
if(user.email === ''){
$scope.loginErrors.push('Please enter your email');
}
else if(user.password === ''){
$scope.loginErrors.push('Please enter your password');
}
else if(user.email === 'Admin'){
$window.location.href = '/#/admin';
} else {
ref.authWithPassword({
email : user.email,
password : user.password
}, function(error, authData) {
if (error) {
switch(error.code) {
case 'INVALID_EMAIL':
$scope.loginShow = true;
$timeout( function(){ $scope.loginMessage = 'Please enter a valid email address'; }, 500);
break;
case 'INVALID_USER':
$scope.loginShow = true;
$timeout( function(){ $scope.loginMessage = 'Please enter a valid user address'; }, 500);
break;
case 'INVALID_PASSWORD':
$scope.loginShow = true;
$timeout( function(){ $scope.loginMessage = 'Please enter the correct password'; }, 500);
break;
default:
console.log('error', error);
}
} else {
console.log('Authenticated successfully with payload:', authData);
$window.location.href = '/#/dashboard';
}
});
}
any help would be appreciated
I had a similar problem when developing and I had two browser tabs up running browser sync. Closed one and the problem went away.

Empty Facebook friends list

So I'm using the "Facebook-sdk" plugin. I'm initializing Facebook like this:
FB.init({ appId: 'xxxxxxxxxxx', cookie: true, xfbml: true, oauth: true, status: true });
FB.login(function(){ // get permissions
}, {scope: 'user_friends, read_friendlists, user_photos, email, publish_actions '});
FB.getLoginStatus(function (response) { // to generate AccessToken
if (response.authResponse) {
console.log('LoginStatusResponse: ' + JSON.stringify(response, null, 4));
} else {
console.log('AuthResponse: No');
}
});
Then in response to a button click event, I'm doing:
'click #get_fb_friends' : function(event, template) {
FB.api(
"/me/friends",
function (response) {
if (response && !response.error) {
console.log('GOT them !!!' + JSON.stringify(response, null, 4));
return response;
} else {
console.log('No can do' + JSON.stringify(response, null, 4));
}
});
}
The thing is that I'm getting an empty Data variable:
GOT them !!!{
"data": []
}
PS: The query "/me" returns all information about myself, it's the "/me/friends" that doesn't work.
Can it be a permissions problem ?
Facebook has changed its api a few weeks ago,you can only access a list of your friends when they have personally accepted to use your app.. Nothing to do about it
Like #Wampie said, the API has changed, so you could try to use the v1 API (keep in mind that you'll need to request a new access token).
And you can still invite friends to your app by using the apprequests method.
FB.ui({
method: 'apprequests',
message: 'You should learn more about the Platform.'
}, function(){
console.log(arguments);
});
Example here:
https://www.fbrell.com/fb.ui/apprequests

Firebase authentication on App initilisation

This is works:
console.log('User ID: ' + user.id + ', Provider: ' + user.provider);
but this one is not:
$scope.authenticated.currentUser = user.id;
My goal here is to take to take some of the authentication variables (Email+UserID) and then use them to access a profile node ON firebase. On initialization I want the username, email, and a few other things I need for the app.
crossfitApp.controller('globalIdCtrl', ["$scope",'defautProfileData','$q', function ($scope,defautProfileData,$q) {
var dataRef = new Firebase("https://glowing-fire-5401.firebaseIO.com");
$scope.authenticated={
currentUser: $scope.authemail,
emailAddress: "",
settings: "",
};
var chatRef = new Firebase('https://<YOUR-FIREBASE>.firebaseio.com');
var auth = new FirebaseSimpleLogin(chatRef, function(error, user) {
if (error) {
// an error occurred while attempting login
switch(error.code) {
case 'INVALID_EMAIL':
case 'INVALID_PASSWORD':
default:
}
} else if (user) {
// user authenticated with Firebase
console.log('User ID: ' + user.id + ', Provider: ' + user.provider);
$scope.authenticated.currentUser = user.id ;//
} else {
// user is logged out
}
});
}]); //GlobaldCtrl
Most likely, you're running into a problem with Angular's HTML Compiler.
Whenever you use an event like ng-click/ng-submit/etc, Angular fires $scope.$apply(), which checks for any changes to your $scope variables and applies them to the DOM.
Since FirebaseSimpleLogin is not part of Angular's purview, it has no idea that when the callback is fired, you've updated $scope.authenticated.currentUser. This would also explain why it works when you call auth.login(), since you're probably invoking that via an ng-click event somewhere, which would fire a digest check and discover the changes.
If this is indeed the case, you can correct this issue by alerting Angular that it needs to run $apply by using $timeout:
crossfitApp.controller('globalIdCtrl', ["$scope",'defautProfileData','$q', '$timeout', function ($scope,defautProfileData,$q, $timeout) {
/* ... */
var auth = new FirebaseSimpleLogin(chatRef, function(error, user) {
if (error) {
/* ... */
} else if (user) {
$timeout(function() {
$scope.authenticated.currentUser = user.id ;//
});
} else {
// user is logged out
}
});

Resources