I'm pretty new to developing in Ionic and I'm trying to integrate my application with Facebook login. I found this tutorial https://ionicthemes.com/tutorials/about/native-facebook-login-with-ionic-framework and I did everything the way it was shown but I'm getting the following error
TypeError: Cannot read property 'getLoginStatus' of undefined
at Scope.$scope.facebookSignIn (controllers.js:547)
at $parseFunctionCall (ionic.bundle.js:21172)
at ionic.bundle.js:53674
at Scope.$eval (ionic.bundle.js:23228)
at Scope.$apply (ionic.bundle.js:23327)
at HTMLAnchorElement.<anonymous> (ionic.bundle.js:53673)
at HTMLAnchorElement.eventHandler (ionic.bundle.js:11841)
at triggerMouseEvent (ionic.bundle.js:2865)
at tapClick (ionic.bundle.js:2854)
at HTMLDocument.tapTouchEnd (ionic.bundle.js:2977)
My Code for the controller is as follows:
.controller('WalkthroughCtrl', function($scope, $state, $q, UserService, $ionicLoading) {
var fbLoginSuccess = function(response) {
if (!response.authResponse){
fbLoginError("Cannot find the authResponse");
return;
}
var authResponse = response.authResponse;
getFacebookProfileInfo(authResponse)
.then(function(profileInfo) {
// For the purpose of this example I will store user data on local storage
UserService.setUser({
authResponse: authResponse,
userID: profileInfo.id,
name: profileInfo.name,
email: profileInfo.email,
picture : "http://graph.facebook.com/" + authResponse.userID + "/picture?type=large"
});
$ionicLoading.hide();
$state.go('app.feeds-categories');
}, function(fail){
// Fail get profile info
console.log('profile info fail', fail);
});
};
// This is the fail callback from the login method
var fbLoginError = function(error){
console.log('fbLoginError', error);
$ionicLoading.hide();
};
// This method is to get the user profile info from the facebook api
var getFacebookProfileInfo = function (authResponse) {
var info = $q.defer();
facebookConnectPlugin.api('/me?fields=email,name&access_token=' + authResponse.accessToken, null,
function (response) {
console.log(response);
info.resolve(response);
},
function (response) {
console.log(response);
info.reject(response);
}
);
return info.promise;
};
//This method is executed when the user press the "Login with facebook" button
$scope.facebookSignIn = function() {
facebookConnectPlugin.getLoginStatus(function(success){
if(success.status === 'connected'){
// The user is logged in and has authenticated your app, and response.authResponse supplies
// the user's ID, a valid access token, a signed request, and the time the access token
// and signed request each expire
console.log('getLoginStatus', success.status);
// Check if we have our user saved
var user = UserService.getUser('facebook');
if(!user.userID){
getFacebookProfileInfo(success.authResponse)
.then(function(profileInfo) {
// For the purpose of this example I will store user data on local storage
UserService.setUser({
authResponse: success.authResponse,
userID: profileInfo.id,
name: profileInfo.name,
email: profileInfo.email,
picture : "http://graph.facebook.com/" + success.authResponse.userID + "/picture?type=large"
});
$state.go('app.feeds-categories');
}, function(fail){
// Fail get profile info
console.log('profile info fail', fail);
});
}else{
$state.go('app.home');
}
} else {
// If (success.status === 'not_authorized') the user is logged in to Facebook,
// but has not authenticated your app
// Else the person is not logged into Facebook,
// so we're not sure if they are logged into this app or not.
console.log('getLoginStatus', success.status);
$ionicLoading.show({
template: 'Logging in...'
});
// Ask the permissions you need. You can learn more about
// FB permissions here: https://developers.facebook.com/docs/facebook-login/permissions/v2.4
facebookConnectPlugin.login(['email', 'public_profile'], fbLoginSuccess, fbLoginError);
}
});
};
})
Thank You in Advance.
Related
I'm creating an app with the ionic framework and integrate the facebookConnectPlugin for login and making posts to a fan page.
The login part is working properly, I can see the user data and display on the app. The problem I'm having is when I try to make a post to facebook.
This is the complete controller that manage the login and the post
.controller('signupCtrl', function($scope, $state, $q, UserService, $ionicLoading){
// This is the success callback from the login method
var accesstoken;
var fbLoginSuccess = function(response){
if (!response.authResponse){
fbLoginError("Cannot find the authResponse");
return;
}
var authResponse = response.authResponse;
accesstoken = authResponse.accessToken;
getFacebookProfileInfo(authResponse).then(function(profileInfo){
// For the purpose of this example I will store user data on local storage
UserService.setUser({
authResponse: authResponse,
userID: profileInfo.id,
name: profileInfo.name,
email: profileInfo.email,
picture: "http://graph.facebook.com/" + authResponse.userID + "/picture?type=large"
});
$ionicLoading.hide();
}, function(fail){
// Fail get profile info
alert('profile info fail ' + fail);
});
};
// This is the fail callback from the login method
var fbLoginError = function(error){
alert('fbLoginError ' + error);
$ionicLoading.hide();
};
// This method is to get the user profile info from the facebook api
var getFacebookProfileInfo = function (authResponse){
var info = $q.defer();
facebookConnectPlugin.api('/me?fields=email,name&access_token=' + authResponse.accessToken, null,
function (response) {
console.log(response);
info.resolve(response);
},
function (response) {
console.log(response);
info.reject(response);
}
);
return info.promise;
};
//This method is executed when the user press the "Login with facebook" button
$scope.facebookSignIn = function(){
console.log('---> facebookSignIn');
facebookConnectPlugin.getLoginStatus(function(success){
if (success.status === 'connected'){
// The user is logged in and has authenticated your app, and response.authResponse supplies
// the user's ID, a valid access token, a signed request, and the time the access token
// and signed request each expire
//alert('getLoginStatus ' + success.status);
// Check if we have our user saved
var user = UserService.getUser('facebook');
if (!user.userID){
alert('UNO');
getFacebookProfileInfo(success.authResponse).then(function(profileInfo) {
// For the purpose of this example I will store user data on local storage
UserService.setUser({
authResponse: success.authResponse,
userID: profileInfo.id,
name: profileInfo.name,
email: profileInfo.email,
picture: "http://graph.facebook.com/" + success.authResponse.userID + "/picture?type=large"
});
//$state.go('menu.home');
}, function(fail){
// Fail get profile info
alert('profile info fail ' + fail);
});
}else{
//alert('DOS');
$state.go('menu.home');
var fan_token = 'EAAH1eElPgZBl1jwZCI0BADZBlrZCbsZBWF5ig29V1Sn5ABsxH1o4kboMhpjZBDfKtD1lfDK1dJLcZBI4gRBOF2XGjOmWMXD0I8jtPZA4xLJNZADarOGx8fiXBRZCTOaxwBLQEwRjsvaqTtb2DTCI0Qdo3haX6vqHlJoWMZD';
console.log('access token', accesstoken);
facebookConnectPlugin.api(
'/186259017448757/feed',
'POST',
{
access_token: fan_token,
'message':'HOLA!'
},
function(response){console.log(response);alert(response.id)}
)
}
}else{
// If (success.status === 'not_authorized') the user is logged in to Facebook,
// but has not authenticated your app
// Else the person is not logged into Facebook,
// so we're not sure if they are logged into this app or not.
alert('getLoginStatus ' + success.status);
$ionicLoading.show({
template: 'Logging in...'
});
// Ask the permissions you need. You can learn more about
// FB permissions here: https://developers.facebook.com/docs/facebook-login/permissions/v2.4
facebookConnectPlugin.login(['email', 'public_profile'], fbLoginSuccess, fbLoginError);
}
});
};
})
This is the part where I try to make a post to a facebook wall
facebookConnectPlugin.api('/181297057448657/feed', 'POST', {access_token: fan_token, 'message':'HOLA!'},
function(response){
console.log(response);
alert(response.id)
}
)
I went to https://developers.facebook.com/tools/explorer to generate the access tokens, tried with several tokens (user, fanpage, etc) but any seem to work. I've also used this code snippet provided in the facebook devs explorer tool
FB.api(
'/174801556748297/feed',
'POST',
{"message":"testing3"},
function(response) {
// Insert your code here
}
);
The result is always the same, I get a JSON error in the response object and no facebook post to the wall
Any help would be really appreciated!
PD: app ID's have been modified, that why they don't match. Same with the tokens and fan page ID
I used following in my app to post ,Reference https://github.com/ccoenraets/sociogram-angular-ionic
$scope.share = function () {
OpenFB.post('/me/feed', $scope.item)
.success(function () {
console.log("done");
$ionicLoading.hide();
$scope.item.message="";
$ionicLoading.show({ template: 'Post successfully on Facebook!', noBackdrop: true, duration: 2000 });
$scope.status = "This item has been shared from OpenFB";
})
.error(function(data) {
$ionicLoading.hide();
alert(data.error.message);
});
};
HTML
<div class="media-body">
<textarea placeholder="What's on your mind?" ng-model="item.message"></textarea>
</div>
<hr style="margin-top: -1px;" />
<div style="text-align:right;padding-right:20px;padding-bottom:10px;">
<button class="fb-login" ng-click="share()">Post to Facebook</button>
</div>
In a MEAN app I am trying to allow an authorised user (email and password login) to change their username.
I can successfully use Postman to PUT a new username to http://localhost:3000/api/users/xxxxxxxxxxxxxxxx.
But the angular code fails.
Here is the relevant part of the edit page:
<form ng-submit="user.saveUser()">
<div class="form-group">
<label> New Username</label>
<input type="text" class="form-control" ng-model="user.userData.name">
</div>
Here is the controller:
.controller('userEditController', function($routeParams, User) {
var vm = this;
vm.type = 'edit';
User.get($routeParams.user_id)
.success(function(data) {
vm.userData = data;
});
// function to save the user
vm.saveUser = function() {
vm.processing = true;
vm.message = '';
// call the userService function to update
User.update($routeParams.user_id, vm.userData)
.success(function(data) {
vm.processing = false;
// clear the form
vm.userData = {};
// bind the message from our API to vm.message
vm.message = data.message;
});
};
});
Here is the service:
// update a user
userFactory.update = function(id, userData) {
return $http.put('/api/users/' + id, userData);
};
at this point userData contains name: “Fred” or whatever was input to the form
and here is the api.js
apiRouter.route('/users/:user_id')
// get the user with that id
.get(function(req, res) {
User.findByIdAndUpdate(req.params.user_id, function(err, user) {
if (err) return res.send(err);
// return that user
res.json(user);
});
})
// update the user with this id
.put(function(req, res) {
console.error(req.params.user_id);
User.findById(req.params.user_id, function(err, user) {
if (err) return res.send(err);
// set the new user information if it exists in the request
if (req.body.name) user.name = req.body.name;
// save the user
user.save(function(err) {
if (err) return res.send(err);
// return a message
res.json({ message: 'User updated!' });
});
});
});
(I had to use findByIdAndUpdate instead of findById because of a CastError.)
Although the console states:
XHR finished loading: PUT http:/localhost/3000/api/users/user_id
The value of req.params.user_id is just user_id.
The terminal shows:
PUT /api/users/user_id 200 4.040 ms - 2273
GET /api/users/user_id - - ms - -
GET /api/users/user_id - - ms - -
GET /api/users/user_id - - ms - -
Like I say Postman can communicate with the API and can update without problems. I am stumped, and hopefully someone will put me out of my misery
I had to change tack with this one. The fact that a manually entered user_id in Postman worked should have told me that the user_id provided by the Angular code was not correct. So I made sure that the JWT included the user_id:
var token = jwt.sign({
name: user.name,
email: user.email,
user_id: user._id
Then added an api endpoint to get user information:
apiRouter.get('/me', function(req, res) {
res.send(req.decoded);
});
Then connected a service:
userFactory.get = function() {
return $http.get('/api/me/');
};
Then in the controller I could call get:
User.get()
.success(function(result) {
$scope.user_id = result.user_id;
});
$scope.user_id now has the correct user_id which I can pass into the update method:
User.update($scope.user_id, vm.userData)
.success(function(data)
So now it works as intended.
I got a service which first need to retrieve an accesstoken and then a User object. When this is done, further UI actions needs to be taken. The problem I have is that login().then() is invoked with a valid Session.accesstoken but a non-resolved promise for the Session.user. So I can't do any logic based on the user's info (e.g. role, etc.)
The following code I have:
In controllers.js (login() is invoked upon form credentials button click)
.controller('LoginController',
function($scope, SessionService) {
$scope.credentials = {
username : '',
password : ''
};
$scope.login =
function() {
SessionService.login($scope.credentials).then(function() {
console.info("succesfully logged in as user " + JSON.stringify(Session));
// further UI actions..
});
};
})
In services.js
.factory('SessionService',
function(User, Session, AuthorizationService) {
return {
login : function(credentials) {
return AuthorizationService.requestToken(credentials)
.then(function(token) {
console.info("Got token: " + token);
if (!!token) {
Session.create(token);
console.info("Fetching user...");
return User.get({
id : 'me'
});
} else {
throw (new Error("Could not log in"));
}
}).then(function(user) {
console.info("Got user: " + user);
if (!!user) {
Session.user = user;
} else {
throw (new Error("Could not fetch user"));
}
});
},
};
})
Here is the output of the console:
Got token: cf9c0eba82d872508f7dcc0b234f0d52 services.js:120
Fetching user...
services.js:124 Got user: [object Object]
services.js:132 succesfully logged in as user
{"token":"cf9c0eba82d772508f7dcc0b234f0d52","user":{"$promise":{},"$resolved":false}}
The User object is created by $resource and is not a promise; it is the actual object that will eventually be populated with the user info, but at this point of the code it contains nothing.
The solution is simple: from the first then do:
return User.get({...}).$promise;
The next then will be invoked with the user object as expected, but only when the data is actually fetched.
What I want:
firebase checks authentication of page load
firebase returns userID if logged in
my function returns the username associated with the user.Id
assign to the variable that represents the username
render!
All on page load
Current Behavior:
The following configuration retrieves the username but will only display the username once I click a login button I have made.For some reason even though I am currently logged in I must click the login button. I want a set up where if I am logged in the app will just know I am logged in from the start!
crossfitApp.controller('globalIdCtrl', ["$scope",'$q','defautProfileData','$timeout', function ($scope,$q,defautProfileData,$timeout) {
var dataRef = new Firebase("https://glowing-fire-5401.firebaseIO.com");
$scope.myFbvar =null;
$scope.authenticated={
currentUser: null,
avatarUrl: "",
emailAddress: "",
settings: "",
currentUserid: null,
};
function getProfile(userID,assignMe){
myprofile= new Firebase("https://glowing-fire-5401.firebaseio.com/profiles/"+userID+"/username");
myprofile.once('value', function(nameSnapshot) {
assignMe = nameSnapshot.val();
});
};
$scope.auth = new FirebaseSimpleLogin(dataRef, function(error, user) {
if (error) {
//Error
console.log ('error');
}
else if (user) {
//logged in
$timeout(function() {
getProfile(user.id,);
});
console.log('logged in');
$scope.authenticated.currentUserid = user.id ;
}
else {
// user is logged out
console.log('logged out');
$timeout(function() {
$scope.authenticated.currentUserid =null;
});
}
});
}]); //Global
In your else if( user ) logic, you forgot to put your scope var inside the $timeout, so it is being set properly, but Angular doesn't learn about it until the next time $apply is called (e.g. ng-click, ng-submit, etc).
Thus:
else if (user) {
//logged in
$timeout(function() {
getProfile(user.id,);
$scope.authenticated.currentUserid = user.id ; // moved into $timeout
});
console.log('logged in');
}
You can read more about why this matters here and here.
im developing an test application in angularjs and authenticating my user from login page,
Express Code:
exports.login = function (req, res, next) {
passport.authenticate('local', function(err, user, info) {
var error = err || info;
if (error) return res.json(401, error);
req.logIn(user, function(err) {
if (err) return res.send(err);
res.json(req);
});
})(req, res, next);
};
Service : (Auth and Session)
Auth Service code:
login: function(user, callback) {
var cb = callback || angular.noop;
return Session.Sessionlogin().save({
email: user.email,
password: user.password
}, function(user) {
$rootScope.currentUser = user;
return cb();
}, function(err) {
return cb(err);
}).$promise;
},
Session Service Code:
Sessionlogin: function(){
return $resource('/api/session/');
Controller Code:
$scope.login = function(form) {
$scope.submitted = true;
if(form.$valid) {
Auth.login({
email: $scope.user.email,
password: $scope.user.password
})
.then( function(err) {
// todo : redirect to admin dashboard
$location.path('admin/dashboard');
})
.catch( function(err) {
err = err.data;
$scope.errors.other = err.message;
});
}
};
every thing work fine now my question is :
after successful login im redirecting the user to dashboard page.Now how can i access the userinfo in dashboard page.Is there any kind of session object in angularjs where i can store the response received from the express code and send it to the dashboard page.
To share data around an angular app, you can either:
Store the data in a service which can then be injected into controllers whenever you need to access that data. Services are singletons: there'll only ever be one instance of each service which is why the data is persistent across controllers.
Store data in $rootScope. It looks like you've already set the user object on the root scope, so you can access it as $rootScope.currentUser provided that you have injected $rootScope into your controller. Note that it's not usually a good idea to litter the root scope, but in this case I think it is wise to store the user object there because you will probably need to access it from a lot of views.
I usually store the user object in $rootScope (so that it's accessible from views) and in a dedicated service (so that it's accessible from controllers/etc).