Halo all,
I want to use angularjs with firebase simple login (facebook). But I have no idea how to
create the auth share service.
What I want to do is
create a authentication service
use this auth service to check if user loggedin in every controllers
controllers will do the $location if user loggedin/not-login
I also new to angularjs but I don't know which services should I use in this situation.
service or factory?
How can I put the below code in angular service then tell each controller if user logged in or not?
var firebaseRef = new Firebase("https://test.firebaseio.com");
var auth = new FirebaseAuthClient(firebaseRef, function(error, user) {
if (user) {
console.log(user);
} else if (error) {
console.log(error);
} else {
console.log('user not login');
}
});
Here is what i'm guessing, return user value from authService so in controllers if authService.user exists then redirect to loggedin page otherwise show login dialog with a
login button to call the following code
authService.login('facebook');
Let me know if I can do like this, or there is a better way?
Here is what I'm using so far...
I haven't implemented the redirecting yet but the rest works.
p4pApp.factory('firebaseAuth', function($rootScope) {
var auth = {},
FBref = new Firebase(p4pApp.FIREBASEPATH);
auth.broadcastAuthEvent = function() {
$rootScope.$broadcast('authEvent');
};
auth.client = new FirebaseAuthClient(FBref, function(error, user) {
if (error) {
} else if (user) {
auth.user = user;
auth.broadcastAuthEvent();
} else {
auth.user = null;
auth.broadcastAuthEvent();
}
});
auth.login = function() {
this.client.login('facebook');
};
auth.logout = function() {
this.client.logout();
};
return auth;
});
The AuthCtrl is common to all/most of my pages.
var AuthCtrl = function($scope, firebaseAuth) {
$scope.login = function() {
firebaseAuth.login();
};
$scope.logout = function() {
firebaseAuth.logout();
};
$scope.isLoggedIn = function() {
return !!$scope.user;
};
// src: Alex Vanston (https://coderwall.com/p/ngisma)
$scope.safeApply = function(fn) {
var phase = this.$root.$$phase;
if (phase == '$apply' || phase == '$digest') {
if(fn && (typeof(fn) === 'function')) {
fn();
}
} else {
this.$apply(fn);
}
};
$scope.$on('authEvent', function() {
$scope.safeApply(function() {
$scope.user = firebaseAuth.user;
});
});
};
Regarding factory vs. service, there was a good blog post explaining how to approach the choice that I recommend reading: http://iffycan.blogspot.com/2013/05/angular-service-or-factory.html
In terms of doing authentication, your general approach of assigning signed in state to a variable in a service seems alright. We're thinking about doing a deeper integration with Angular for authentication, but for now this seems like a reasonable approach.
Related
I have only been able to track down this link to solve my problem. I am trying to use protractor to run e2e testing. This is my first go at it, and I like it. However my project requires Google Authentication, then once authenticated, I compare it to my database to make sure the user is in the project. I cannot figure out from the stackoverflow post how to call to the Google Auth page object demee is talking about in the last answer. Also the first person says to find element by.id('Email') and by.id('Passwd') which may be a problem, because my google auth is coming up in another window. So I am not sure how to call to that with Protractor. Here is some of my code after I initialize the $window once gapi is loaded:
.controller('ContainerController', ['$scope', '$rootScope', '$state','$window', '$location','employeeFactory', 'employeeTestFactory', function ($scope, $rootScope, $state, $window,$location, employeeFactory, employeeTestFactory) {
$rootScope.callRequests=function(){};
$rootScope.callInfo=function(){};
if(typeof $rootScope.gapi !== "undefined")gapi.load('client:auth2', initClient);
$rootScope.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams){
if(typeof $rootScope.gapi === "undefined") return;
gapi.load('client:auth2', initClient);
})
$scope.$state = $state;
$window.initGapi = function() {
gapi.load('client:auth2', initClient);
$rootScope.gapi = gapi;
}
$rootScope.calculateUsed = function(val){
$rootScope.employee.timePending = $rootScope.employee.timePending = 0;
var newTimeUsed = 0;
angular.forEach(val, function(key, value){
var td = key.timeDuration;
if(key.timeState === "pending"){
$rootScope.employee.timePending += Number(td);
}else{
newTimeUsed += Number(td);
}
});
$rootScope.employee.totalTimeUsed = newTimeUsed;
}
$scope.employeeType = $rootScope.email = "";
function initClient() {
gapi.client.init({
apiKey: 'AIzaSyDaMf0eviuFygt1hzwQz03a2k2lrLDnpIc',
discoveryDocs: ["https://people.googleapis.com/$discovery/rest?version=v1"],
clientId: '977491754644-954b83j2evmq65v6kchq4dsd9j0ud4vg.apps.googleusercontent.com',
scope: 'profile'
}).then(function () { gapi.auth2.getAuthInstance().isSignedIn.listen(updateSigninStatus); updateSigninStatus(gapi.auth2.getAuthInstance().isSignedIn.get());
$scope.employee = [];
});
}
function updateSigninStatus(isSignedIn) {
if (isSignedIn) {
getEmailAddress();
}else{
$state.go('app');
}
}
$scope.handleSignInClick = function(event) {
if(!gapi.auth2.getAuthInstance().isSignedIn.get()){
gapi.auth2.getAuthInstance().signIn();
}
}
$scope.handleSignOutClick = function(event) {
if(gapi.auth2.getAuthInstance().isSignedIn.get()){
gapi.auth2.getAuthInstance().signOut();
}
}
function getEmailAddress() {
gapi.client.people.people.get({
resourceName: 'people/me'
}).then(function(response) {
$rootScope.email = response.result.emailAddresses[0].value;
$rootScope.callRequests();
$rootScope.callInfo();
//Here is where I compare google to my db and route users back to main if not in db employeeTestFactory.get($rootScope.email).then(function(message) {
if(typeof message.employeeid === "undefined"){
$state.go('app');
}else if($location.path() === "/"){
$state.go('app.employee');
$rootScope.employee = message;
}else{
$rootScope.employee = message;
}
});
}, function(reason) {
console.log('Error: ' + reason.result.error.message);
});
}
}])
.controller('LoginController', ['$scope', '$state', '$window', '$http','$rootScope', '$timeout', 'GooglePlus', 'gapiService', function ($scope, $state, $window, $http, $rootScope, $timeout, GooglePlus, gapiService) {
$scope.$state = $state;
$scope.callme = function(){
$scope.handleSignInClick();
}
// if it could not be loaded, try the rest of
// the options. if it was, return it.
var url;
var windowThatWasOpened;
$http.get("url").then(function(response) {
url = response.data;
});
$scope.login = function() {
windowThatWasOpened = $window.open(url, "Please sign in with Google", "width=500px,height=700px");
}
window.onmessage = function(e) {
if(windowThatWasOpened) windowThatWasOpened.close();
var urlWithCode = e.data;
var idx = urlWithCode.lastIndexOf("code=");
if(idx === -1) return;
var code = urlWithCode.substring(idx + 5).replace("#","");
$http.get("token?code=" + code).then(function(response) {
var userurl = 'https://www.googleapis.com/plus/v1/people/me?access_token='+response.data.access_token;
$http.get(userurl).then(function(response) {
console.log("user info: "+JSON.stringify(response.data));
})
});
}
}])
And here is the code I am trying to navigate to google with:
describe('Protractor Demo App', function() {
it('should have a title', function() {
browser.get('http://localhost:9000/');
element(by.id('gLogin')).click().then(function(){
Google.loginToGoogle();
});
expect(browser.getTitle()).toEqual('TrinityIT Time Off Tracking');
browser.sleep(5000);
});
});
And here is my conf file:
exports.config = {
framework: 'jasmine',
specs: ['googlePage.js','spec.js'],
onPrepare: function () {
global.isAngularSite = function (flag) {
console.log('Switching to ' + (flag ? 'Asynchronous' : 'Synchronous') + ' mode.')
browser.ignoreSynchronization = !flag;
},
global.BROWSER_WAIT = 5000;
}
}
Assuming that what you're looking to do is test your app, rather than test the OAuth dialogue, then there is an easier approach.
First an OAuth refresher, the whole point of doing all the OAuth stuff is that you end up with an Access Token that you can include as an "Authorization: Bearer xxxxx" HTTP Header with your Google API (eg. Drive, YouTube, Calendar, etc) requests. Sooooooo, if you had an Access Token, you could bypass all the OAuth stuff and your app will be active and able to be tested.
So, what you want is an automated way to get an Access Token. That's pretty simple. Somewhere, either in your app code or in your Protractor preamble scripts, you need to ingest a Refresh Token, and use that to generate an Access Token which is available to your app.
I do this with a file refreshtoken.js which I carefully do NOT check in to git for security reasons. refreshtoken.js is
var refreshtoken="1x97e978a7a0977...";
var client_id="423432423#gfgfd";
If you look at the answer to How do I authorise an app (web or installed) without user intervention? (canonical ?), you will see the steps to get a Refresh Token, and at the bottom, some JavaScript to show how to use the Refresh Token to fetch an Access Token. It might look like a lot of steps, but you only ever do them once, so it's not too onerous.
This approach bypasses OAuth, so isn't the answer if it's specifically OAuth that you want to test. However it does allow you to test your app in a much more robust manner. It also has the benefit that it can be used for Karma unit testing as well as Protractor e2e testing.
I am building an angular+firebase app with user authentication (with angularfire 0.8).
I need to use onAuth() auth event handler, since I will provide multiple authentication paths, included social, and want to avoid code duplication. Inside onAuth callback, I need to reset location.path to '/'.
Usually everything works nicely, but, if app is loaded on an already authenticated session (<F5>, for example), on $scope.$apply() I get "Error: [$rootScope:inprog] $apply already in progress"
(if I don't use $scope.$apply(), location path is not applyed to scope, and no page change happens).
I suspect I make some stupid mistake, but can't identify it...
This is my workflow:
app.controller('AuthCtrl', function ($scope, $rootScope, User) {
var ref = new Firebase(MY_FIREBASE_URL);
$scope.init = function () {
$scope.users = [];
User.all.$bindTo($scope, 'users').then(function () {
console.info('$scope.users bound:', $scope.users);
});
};
$scope.login = function () {
ref.authWithPassword({
email: $scope.user.email,
password: $scope.user.password,
}, function(err) {
if (err) {
console.error('Error during authentication:', err);
}
});
};
ref.onAuth(function(authData) {
if (authData) {
console.info('Login success');
var $rootScope.currentUser = $scope.users[authData.uid];
$location.path('/');
$scope.$apply();
} else {
console.info('Logout success');
}
});
};
app.factory('User', function ($firebase) {
var ref = $firebase(new Firebase(MY_FIREBASE_URL + 'users'));
return {
all: ref.$asObject()
};
});
Just as a reference, I want to post the solution I found, and I'm currently adopting:
$scope.init = function () {
$scope.params = $routeParams;
$scope.debug = CFG.DEBUG;
$scope.lastBuildDate = lastBuildDate;
$scope.error = null;
$scope.info = null;
$scope.users = [];
User.all.$bindTo($scope, 'users').then(function () {
// watch authentication events
refAuth.onAuth(function(authData) {
$scope.auth(authData);
});
});
...
};
...
I.e., it was enough to move the watch on authentication events inside the callback to bindTo on users object from Firebase.
I'm using angularFireAuth and I want to retrieve the logged in user's info and use in
all the controllers or services when the app is initial.
Currently, I used this in every controller but i having some problem.
$scope.$on("angularFireAuth:login", function(evt, user){
console.log(user);
});
The callback will not call if it is not a full page load or return null when app initial.
I need some tips for how can I return the authenticated user's info so I can use when app is initial and in all the controllers and services.
Example
When in controller or services
$scope.auth.user.id will return user's ID
$scope.auth.user.name will return user's name
etc
I would start with a userService for this:
angular.module('EventBaseApp').service('userService', function userService() {
return {
isLogged: false,
username: null
}
});
And write a LoginCtrl controller:
angular.module('EventBaseApp')
.controller('LoginCtrl', function ($scope, userService, angularFireAuth) {
var url = "https://example.firebaseio.com";
angularFireAuth.initialize(url, {scope: $scope, name: "user"});
$scope.login = function() {
angularFireAuth.login("github");
};
$scope.logout = function() {
angularFireAuth.logout();
};
$scope.$on("angularFireAuth:login", function(evt, user) {
userService.username = $scope.user;
userService.isLogged = true;
});
$scope.$on("angularFireAuth:logout", function(evt) {
userService.isLogged = false;
userService.username = null;
});
});
Inject the userService anywhere you want the user.
My app that am currently working on that uses this - https://github.com/manojlds/EventBase/blob/master/app/scripts/controllers/login.js
Based on ideas presented here - http://blog.brunoscopelliti.com/deal-with-users-authentication-in-an-angularjs-web-app
i'm not sure quite what your question is. but if you are looking to authorise once rather than in each controller, you can put the code into the module instead and put it into the $rootScope.
var myapp = angular.module('myapp').run(
function ($rootScope) {
$rootScope.user = null;
$rootScope.$on("angularFireAuth:login", function (evt, user) {
$rootScope.user = user;
});
});
I am looking for a solid way to have the 'current user id' in all my controllers available.
Using: Firebase Simple Login : Email / Password Authentication
My ida: I need a 'Factory' wich I can inject into my controllers,
to have the 'current user id' always available.
I came up with this code:
app.factory('User', ['angularFire',
//Get Current UserID
function(angularFire){
console.log ('FACTORY: User');
var currentUser = {};
var ReturnStr = '';
var ref = new Firebase("https://myFIREBASE.firebaseio.com/");
var authClient = new FirebaseAuthClient(ref, function (err, user) {
if (err) {
ReturnStr = 'FACTORY: User Error: ' + err;
console.log (ReturnStr);
//var User = ReturnStr;
} else if (user) {
console.log ('FACTORY: User: Login successfully:');
console.log (user);
currentUser = user;
} else {
//console.log ('-----------User: Logged Out ---------------');
ReturnStr = 'FACTORY: Logged out: Redirect to Login';
console.log (ReturnStr);
window.location.href = "/login.php";
}
});
return currentUser;
}
]);
My simplest Controller looks like:
function ToDoCtrl($scope, User) {
$scope.MyUser = User;
$scope.MyUser.test = 'Test';
}
In HTML (angular partials) i have:
<h2>{{MyUser.id}}</h2>
<h2>{{MyUser.email}}</h2>
<h2>{{MyUser.provider}}</h2>
<h2>{{MyUser.test}}</h2>
=> id, email, provider are 'undefined'. In console I see the 'FACTORY: User: Login successfully:' with correct user - Object.
=> Asynchronous loading of data problem?
I have also experimented (without luck):
$timeout(function () {
currentUser = user;
}
Such a FACTORY would be very useful!
Thanks for a pointing me in the right direction!
Edit 1.1: Now, with $rootscope hack
=> Same effect - mycontroller is too fast - factory to slow.
app.factory('User', ['$rootScope', '$timeout', 'angularFire',
//Aktueller Benutzer auslesen
function($rootScope, $timeout, angularFire){
console.log ('FACTORY: User');
var currentUser = {};
var ReturnStr = '';
var ref = new Firebase("https://openpsychotherapy.firebaseio.com/");
var authClient = new FirebaseAuthClient(ref, function (err, user) {
if (err) {
ReturnStr = 'FACTORY: User Error: ' + err;
console.log (ReturnStr);
//var User = ReturnStr;
} else if (user) {
console.log ('FACTORY: User: Login successfully:');
//currentUser = user;
$timeout(function () {
ReturnStr = 'FACTORY: Inside timout';
console.log (ReturnStr);
currentUser = user;
console.log (currentUser);
$rootScope.myUser = user;
$rootScope.myUserID = user.id;
$rootScope.loggedIn = true;
$rootScope.$apply();
return currentUser;
});
} else {
//console.log ('-----------User: Logged Out ---------------');
ReturnStr = 'FACTORY: Logged out: Redirect to Login';
console.log (ReturnStr);
//var User = ReturnStr;
window.location.href = "/login.php";
}
});
return currentUser;
}
]);
TAHNKS for any helpful suggestions! Wonderin how others solve this!
So here is my solution to this exact problem. I am using Firebase, FirebaseAuthClient, and angularFire for my Angular app. I ran into the same situation for my login system where you cannot inject the $scope into the factory and therefore I came up with making a controller that used a factory for it's methods to retrieve, add, update, and delete things. And in the controller, I have my firebaseAuth stuff going on, the setting of the User values, and references whick I assign to the scope of that. Once the user is logged in, they are redirected to another location, at which point the app.js file takes over with a child controller when at that address location.
My login also uses localStorage, so logins will persist, you can refresh and not have to keep logging in, and you can change it to be cookies or sessionStorage easy enough.
This is going to need to be adapted for your needs specifically if you choose to use this method, it's quite complex no matter what, but this is very solid for me and I'm no longer needing to worry about firebaseAuth or angularFire stuff now that my factories are all setup for passing data back and forth. I'm just doing angularJS stuff mostly with directives. So here's my code.
NOTE: This will need modifying, and some things will be pseudo or open-ended for you to figure out for your needs.
AuthCtrl.js
'use strict';
angular.module('YOUR_APP', []).
controller('AuthCtrl', [
'$scope',
'$location',
'angularFire',
'fireFactory',
function AuthCtrl($scope, $location, angularFire, fireFactory) {
// FirebaseAuth callback
$scope.authCallback = function(error, user) {
if (error) {
console.log('error: ', error.code);
/*if (error.code === 'EXPIRED_TOKEN') {
$location.path('/');
}*/
} else if (user) {
console.log('Logged In', $scope);
// Store the auth token
localStorage.setItem('token', user.firebaseAuthToken);
$scope.isLoggedIn = true;
$scope.userId = user.id;
// Set the userRef and add user child refs once
$scope.userRef = fireFactory.firebaseRef('users').child(user.id);
$scope.userRef.once('value', function(data) {
// Set the userRef children if this is first login
var val = data.val();
var info = {
userId: user.id,
name: user.name
};
// Use snapshot value if not first login
if (val) {
info = val;
}
$scope.userRef.set(info); // set user child data once
});
$location.path('/user/' + $scope.userRef.name());
} else {
localStorage.clear();
$scope.isLoggedIn = false;
$location.path('/');
}
};
var authClient = new FirebaseAuthClient(fireFactory.firebaseRef('users'), $scope.authCallback);
$scope.login = function(provider) {
$scope.token = localStorage.getItem('token');
var options = {
'rememberMe': true
};
provider = 'twitter';
if ($scope.token) {
console.log('login with token', $scope.token);
fireFactory.firebaseRef('users').auth($scope.token, $scope.authCallback);
} else {
console.log('login with authClient');
authClient.login(provider, options);
}
};
$scope.logout = function() {
localStorage.clear();
authClient.logout();
$location.path('/');
};
}
]);
And now for the nice and simple yet quite reusable factory. You will need to set your Firebase path for your app for the baseUrl variable for it to work.
fireFactory.js
'use strict';
angular.module('YOUR_APP').
factory('fireFactory', [
function fireFactory() {
return {
firebaseRef: function(path) {
var baseUrl = 'https://YOUR_FIREBASE_PATH.firebaseio.com';
path = (path !== '') ? baseUrl + '/' + path : baseUrl;
return new Firebase(path);
}
};
}
]);
Info
You give the factory just a piece of the path reference such as 'users' which will be used as part of the full path ref to where you want to store your user data.
fireFactory.firebaseRef('users')
Once you have a reference set for a user, they won't need to be set again it will just use the existing data and .auth() to it. Additionally if there's an existing 'token' in localStorage it will use that to auth() the user too.
Otherwise, it will login() the user and pop open the Oauth windows for them to do so using whatever option you provide them.
I have spent a lot of time, many many hours days and yes even months searching for something better than this when it comes to Firebase/FirebaseAuthClient and angularFire. With the way the Firebase API and FireAuth API is, it's very annoying to make them play nicely with each other when using them with angularFire anyways. It's very frustrating but I've gotten past it finally.
If you want to check out the code for my app and see how I'm doing these things more completely, you can find it in this branch of my Webernote github repo.
Feel free to fork it, install and run it locally, or contribute to it even if you like. I could use some help myself :)
Hope this helps you!!
Here's the way I do it.
First of all I have my firebase auth service (I'm not using Angularfire) that calls off to Singly to handle logins. When the user status changes it $broadcasts an event.
p4pApp.factory('firebaseAuth', function($rootScope, singlyAuth) {
var auth = {},
FBref = new Firebase(p4pApp.FIREBASEPATH);
auth.login = function(service) {
singlyAuth.login(service);
};
auth.logout = function() {
FBref.unauth();
auth.user = null;
auth.broadcastAuthEvent();
};
auth.broadcastAuthEvent = function() {
$rootScope.$broadcast('authEvent');
};
auth.authWithToken = function(token) {
if (token !== undefined) {
FBref.auth(token, function(error, authData) {
if(!error) {
auth.user = authData.auth.account;
auth.broadcastAuthEvent();
} else {
auth.user = null;
auth.broadcastAuthEvent();
}
}, function(error) {
auth.user = null;
auth.broadcastAuthEvent();
});
}
};
return auth;
});
Then I have a 'top level' controller that looks after authorisation state.
var AuthCtrl = function($scope, firebaseAuth, singlyAuth, firebase, user) {
$scope.user = null;
$scope.logout = function() {
firebaseAuth.logout();
};
$scope.isLoggedIn = function() {
return !!$scope.user;
};
// src: Alex Vanston (https://coderwall.com/p/ngisma)
$scope.safeApply = function(fn) {
var phase = this.$root.$$phase;
if (phase == '$apply' || phase == '$digest') {
if(fn && (typeof(fn) === 'function')) {
fn();
}
} else {
this.$apply(fn);
}
};
$scope.$on('authEvent', function() {
$scope.safeApply(function() {
$scope.user = firebaseAuth.user;
});
user.setID(firebaseAuth.user);
if (firebaseAuth.user) {
firebase.fetch(['users', firebaseAuth.user], function(results) {
if (results) {
user.setData(results);
} else {
results = {};
results.createdAt = DateTimeStamp();
}
results.lastLogin = DateTimeStamp();
firebase.set('users', firebaseAuth.user, results);
});
} else {
user.clearData();
}
});
};
Finally, I use a dedicated user service to maintain user state. (It's still in development)
p4pApp.factory('user', function() {
var userService = {}, user={};
user.data = {};
userService.setID = function(id) {
user.id = id;
};
userService.getID = function() {
return user.id;
};
userService.setData = function(data) {
user.data = data || {};
};
userService.getData = function() {
return user.data;
};
userService.clearData = function() {
user.data = {};
};
userService.setDataField = function(field, data) {
user.data[field] = data;
};
userService.clearDataField = function(field) {
delete user.data[field];
};
userService.pushData = function(key, data) {
if (typeof(key) === 'string') {
user.data[key] = data;
} else {
_.reduce(key, function(obj, child, index, list) {
obj[child] = obj[child] || {};
if (index == list.length-1) {
obj[child] = data;
}
return obj[child];
}, user.data);
}
};
userService.deleteData = function(key) {
if (typeof(key) === 'string') {
delete user.data[key];
} else {
_.reduce(key, function(obj, child, index, list) {
obj[child] = obj[child] || {};
if (index == list.length-1) {
delete obj[child];
return;
}
return obj[child];
}, user.data);
}
};
return userService;
});
This is most probably due to async nature of the call. To fix it you would have to
Inject $scope into the factory function (similar to angularFire dependency)
Use $scope.$apply() after the assigment currentUser = user;
Another solution that works for me:
account.service.js
(function() {
'use strict';
angular
.module('app.account')
.factory('Account', Account);
Account.$inject = [
'$firebaseAuth',
'$firebaseObject'
];
/* #ngInject */
function Account(
$firebaseAuth,
$firebaseObject,
) {
var firebaseRef = new Firebase('https://<<-- MY_FIREBASE -->>.firebaseio.com');
var authObj = $firebaseAuth(firebaseRef);
var service = {
userInfo: null
};
activate();
return service;
////////////////
function activate() {
// Add listeners for authentication state changes
authObj.$onAuth(function(authData) {
if (authData) {
// Load the userInfo
loadUserInfo(authData);
} else {
// Destroy the userInfo Object if one exists
if (service.userInfo) {
service.userInfo.$destroy();
service.userInfo = null;
}
}
});
}
function loadUserInfo(authData) {
var userRef = firebaseRef.child('users').child(authData.uid);
var loadedInfo = $firebaseObject(userRef);
loadedInfo.$loaded()
.then(function() {
service.userInfo = loadedInfo;
})
.catch(function(error) {
switch (error.code) {
case 'PERMISSION_DENIED':
alert('You don\'t have the permission to see that data.');
break;
default:
alert('Couldn\'t load the user info.');
}
});
}
}
})();
some-component.controller.js
(function() {
'use strict';
angular
.module('app')
.controller('SomeController', SomeController);
SomeController.$inject = [
'Account'
];
/* #ngInject */
function SomeController(
Account
) {
var vm = this;
vm.userInfo = userInfo;
////////////////
function userInfo() {
return Account.userInfo;
}
...
}
})();
some-component.html
...
<div class="user-id">
{{vm.userInfo().id}}
<div>
...
I am using firebase simple login auth with angularjs and I want to create a single page app.
Before this, I have tried using service, main controller to handle it but I don't think it is good enough because I have to call FirebaseAuthClient() every time there is a route.
I also try to put FirebaseAuthClient() in angularjs .run() which initialize when app is start.
But it won't work when there is a route, I think it is because not a full page load.
Ok,
And here is what I want,
except login page, every route (pages) are required login.
A global FirebaseAuthClient() checking on every route so I don't need to call it again.
A global user which return from FirebaseAuthClient()
I'm not sure I understand. You only need to initialize FirebaseAuthClient and all login() once in your entire app. It's a singleton, and your auth credentials apply to any Firebase operations you perform.
What makes you think that this is not the case? What sorts of errors are you seeing?
Here is what I was using before moving auth over to Singly. Maybe it helps?
p4pApp.factory('firebaseAuth', function($rootScope) {
var auth = {},
FBref = new Firebase(p4pApp.FIREBASEPATH);
auth.broadcastAuthEvent = function() {
$rootScope.$broadcast('authEvent');
};
auth.client = new FirebaseAuthClient(FBref, function(error, user) {
if (error) {
} else if (user) {
auth.user = user;
auth.broadcastAuthEvent();
} else {
auth.user = null;
auth.broadcastAuthEvent();
}
});
auth.login = function() {
this.client.login('facebook');
};
auth.logout = function() {
this.client.logout();
};
return auth;
});
The AuthCtrl is common to all/most of my pages.
var AuthCtrl = function($scope, firebaseAuth) {
$scope.login = function() {
firebaseAuth.login();
};
$scope.logout = function() {
firebaseAuth.logout();
};
$scope.isLoggedIn = function() {
return !!$scope.user;
};
// src: Alex Vanston (https://coderwall.com/p/ngisma)
$scope.safeApply = function(fn) {
var phase = this.$root.$$phase;
if (phase == '$apply' || phase == '$digest') {
if(fn && (typeof(fn) === 'function')) {
fn();
}
} else {
this.$apply(fn);
}
};
$scope.$on('authEvent', function() {
$scope.safeApply(function() {
$scope.user = firebaseAuth.user;
});
});
};
From within the AuthCtrl you can just call isLoggedIn() to see if the user is logged in or not.