Unknown provider: currentAuthProvider <- currentAuth on AngularFire v2 Firebase v3 - angularjs

I am trying to make user login and go on from / route in my angularfire app. But, somehow I got Unknown Provider Error while I am in MainController.
Here is my work;
var app = angular.module("myApp", ['firebase', 'ngRoute']);
This the factory of firebaseAuth.
app.factory("Auth", ["$firebaseAuth",
function($firebaseAuth) {
return $firebaseAuth();
}
]);
This is from authenticating with routers angularfire tutorial.
app.run(["$rootScope", "$location", function($rootScope, $location) {
$rootScope.$on("$routeChangeError", function(event, next, previous, error) {
if (error === "AUTH_REQUIRED") {
$location.path("/login");
}
});
}]);
app.config(["$routeProvider", function($routeProvider) {
$routeProvider.when("/login", {
controller: "LoginController",
templateUrl: "views/login.html",
resolve: {
"currentAuth": ["Auth", function(Auth) {
return Auth.$waitForSignIn();
}]
}
}).when("/", {
controller: "MainController",
templateUrl: "views/home.html",
resolve: {
"currentAuth": ["Auth", function(Auth) {
return Auth.$requireSignIn();
}]
}
});
}]);
In the login page I can sign in via google pop up and I can see the cookie in the browser.
app.controller("LoginController", ["$scope", "currentAuth", "Auth", function($scope, currentAuth, Auth) {
$scope.auth = Auth;
$scope.auth.$onAuthStateChanged(function(firebaseUser) {
$scope.firebaseUser = firebaseUser;
});
}]);
When I open "/" path, it fails and creating error like this
app.controller("MainController", [ "$scope", "$location", "$firebaseArray", "currentAuth", function($scope, $location, $firebaseArray, currentAuth) {
var ref = firebase.database().ref();
if (currentAuth == undefined || currentAuth == null) {
$location.path('/login');
}
}]);
Is there something wrong that I miss ?
Thank you.

Related

How can I prevent access to an Angular page if the user IS logged in with AngularFire?

I feel like this is really easy but I'm not sure why I can't figure it out.
For example if we want to restrict access to a page if a user is not logged in we can do something like:
// == LISTEN FOR ROUTE ERRORS
app.run(['$rootScope', '$location', function($rootScope, $location) {
$rootScope.$on('$routeChangeError', function(event, next, previous, error) {
if (error === 'AUTH_REQUIRED') {
$location.path('/login');
}
});
}]);
// == RETURN AUTH SERVICE
app.factory('Authentication', ['$firebaseAuth', function($firebaseAuth) {
return $firebaseAuth();
}]);
// == APP ROUTER
app.config(['$routeProvider', '$location', function($routeProvider, $location) {
$routeProvider
.when('/account', {
controller: 'userController',
templateUrl: 'views/account.html',
resolve: {
"currentAuth": ['Authentication', function(Authentication) {
return Authentication.$requireSignIn(); // if rejected throws $routeChangeError
}]
}
})
}]);
Now what if I want to add a resolve to the '/login' route so that if the user is logged in I can just force them to the account page or a success page?
.when('/login', {
controller: 'userController',
templateUrl: 'views/login.html',
resolve: {
"currentAuth": [function() {
// reject if the user is already logged in
}]
}
});
.when('/login', {
controller: 'userController',
templateUrl: 'views/login.html',
resolve: {
"currentAuth": ['$q', function($q) {
var p = $q.defer();
if (Authentication.$getAuth()) {
p.reject({code: someErrorCode, message: 'Already logged in'});
} else {
p.resolve();
}
return p.promise;
}]
}
});
You should also handle the scenario when logged in, in $routeChangeError or $stateChangeError

Unable to redirect to new page using $location.path with Firebase login

Issue: On Firebase login, I would like to redirect the user to a new page.I am trying to use $location.path() in my controller even I tried using $state.go(). But it seems to be no use. Also I am not getting any error in console.
Using Firebase signInWithEmailAndPassword method, Angularjs 1.5, ui-router and AngularFire.
login.service.js
var firebaseAuthObject = fbDbConn.auth();
function login(emailid, passwd) {
return firebaseAuthObject.signInWithEmailAndPassword(emailid, passwd);
}
login.controller.js
(function() {
'use strict';
angular
.controller('AuthController', AuthController);
AuthController.$inject = ['$scope', '$location', 'authService'];
function AuthController($scope, $location, authService) {
$scope.message = null;
$scope.error = null;
$scope.register = function() {
return authService.register($scope.email, $scope.password)
.then(function(userData) {
$scope.message = "User created with uid: " + userData.uid;
}).catch(function(error) {
$scope.error = error;console.log(error);
});
};
$scope.login = function() {
$scope.auth_error ="";
return authService.login($scope.email, $scope.password)
.then(function(authData) {
$location.path('/app/overview'); //$state.go('/app/overview');
}).catch(function(error) {console.log(error);
$scope.error = error;
$scope.auth_error = "Username or Password is wrong.";
});
};
$scope.logout = function() {console.clear();
authService.logout();
$location.path('/login');
};
}
})();
config.route.js
(function() {
'use strict';
angular
.module('singApp.login', ['ui.router','firebase'])
.config(configFunction)
.run(runFunction);
configFunction.$inject = ['$stateProvider'];
function configFunction($stateProvider) {
$stateProvider
.state('login', {
url: '/login',
templateUrl: 'app/modules/login/login.html'
})
}
runFunction.$inject = ['$location', 'authService', 'firebaseDataService', 'PROTECTED_PATHS'];
function runFunction($location, authService, firebaseDataService, PROTECTED_PATHS) {
authService.firebaseAuthObject.onAuthStateChanged(function(authData) {
if (!authData && pathIsProtected($location.path())) {
authService.logout();
$location.path('/login');
};
});
function pathIsProtected(path) {
return PROTECTED_PATHS.indexOf(path) !== -1;
}
}
})();
Thanks for help !!
first you should inject $state to your controller and use $state.go('stateName')
$state.go('/app/overview') will not work
you should use $state.go('stateName')
angular
.controller('AuthController', AuthController);
AuthController.$inject = ['$scope', '$location','$state', 'authService'];
function AuthController($scope, $location, $state,authService) {
$scope.message = null;
$scope.error = null;
$scope.register = function() {
return authService.register($scope.email, $scope.password)
.then(function(userData) {
$scope.message = "User created with uid: " + userData.uid;
}).catch(function(error) {
$scope.error = error;console.log(error);
});
};
$scope.login = function() {
$scope.auth_error ="";
return authService.login($scope.email, $scope.password)
.then(function(authData) {
$state.go('stateName');
}).catch(function(error) {console.log(error);
$scope.error = error;
$scope.auth_error = "Username or Password is wrong.";
});
};
$scope.logout = function() {console.clear();
authService.logout();
$location.path('/login');
};
}
})();
Just check the $state.go() method instead of $location
First inject the dependency '$state'
AuthController.$inject = ['$scope', '$state', 'authService'];
Check your routes.js file.
The below is a sample code.
app.config(function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/profile");
$stateProvider
.state('login', {
url: '/',
templateUrl: 'login.html'
})
.state('app.overview', {
url: '/overview',
templateUrl: 'views/overview.html'
})
});
If everything correct then then you can use the below code for redirection.
$state.go('login');
I'm using the '$stateChangeSuccess' event to find out the route changes.
app.run(['$rootScope', '$state', '$stateParams', '$cookies', '$timeout',
function($rootScope, $state, $stateParams, $cookies, $timeout) {
$rootScope.$state = $state;
$rootScope.$stateParams = $stateParams;
$rootScope.$on('$stateChangeSuccess', function(event, nextRoute, toState) {
console.log(nextRoute.name);
// $state.go('login');
});
}
])

AngularJS - Hook Routes Changing and Centralize the logic upon that

This question comes from another one: AngularJS - Determine if the view should be displayed by an ajax call result upon the route changes
As to my previous question, finally I came to this solution:
(function() {
'use strict';
angular.module("appClubS", ["appClubS.userModule", "appClubS.productModule", "clubsServices", "ngRoute", "ui.bootstrap"])
.config(routeConfigurator);
angular.module("appClubS")
.controller("checkLoginCtrl", checkLoginController);
checkLoginController.$inject = ['$scope', '$rootScope', '$location', 'userFactory'];
routeConfigurator.$inject = ['$routeProvider', '$locationProvider'];
function routeConfigurator($routeProvider, $locationProvider) {
$routeProvider.when("/home", {
templateUrl: "views/index.html"
});
// ...
// the routes that visitor cannot access before signing in
$routeProvider.when("/account-profile/my-redeem", {
templateUrl: "views/member_zone/my.redeem.html",
resolve: {
loggedin: ["$q", "userFactory", "$location", function checkPermit($q, userFactory, $location) {
var deferred = $q.defer();
var logStatus = userFactory.loggedin();
if (logStatus) {
deferred.resolve({
message: "Proceed to change route."
});
}
else {
deferred.reject({
message: "Redirect to the default page."
});
alert("Please Login First!");
$location.path("/login");
}
return deferred.promise;
}]
}
});
$routeProvider.when("/account-profile/my-survey", {
templateUrl: "views/member_zone/my.survey.html",
resolve: {
loggedin: ["$q", "userFactory", "$location", function checkPermit($q, userFactory, $location) {
var deferred = $q.defer();
var logStatus = userFactory.loggedin();
if (logStatus) {
deferred.resolve({
message: "Proceed to change route."
});
}
else {
deferred.reject({
message: "Redirect to the default page."
});
alert("Please Login First!");
$location.path("/login");
}
return deferred.promise;
}]
}
});
// ...
}
})();
However, I have repeated the same piece of code for each route I would like to forbid undesired access. So now my question is how to do it once for all. I have tried the code as below:
(function() {
'use strict';
angular.module("appClubS", ["appClubS.userModule", "appClubS.productModule", "clubsServices", "ngRoute", "ui.bootstrap"])
.config(routeConfigurator);
angular.module("appClubS")
.controller("checkLoginCtrl", checkLoginController);
checkLoginController.$inject = ['$scope', '$rootScope', '$location', 'userFactory'];
routeConfigurator.$inject = ['$routeProvider', '$locationProvider'];
function routeConfigurator($routeProvider, $locationProvider) {
$routeProvider.when("/home", {
templateUrl: "views/index.html"
});
// ...
// the routes that visitor cannot access before signing in
$routeProvider.when("/account-profile/my-redeem", {
templateUrl: "views/member_zone/my.redeem.html",
resolve: {
loggedin: ["$q", "userFactory", "$location", checkPermit]
}
});
$routeProvider.when("/account-profile/my-survey", {
templateUrl: "views/member_zone/my.survey.html",
resolve: {
loggedin: ["$q", "userFactory", "$location", checkPermit]
}
});
// ...
}
function checkPermit($q, userFactory, $location) {
var deferred = $q.defer();
var logStatus = userFactory.loggedin();
if (logStatus) {
deferred.resolve({
message: "Proceed to change route."
});
}
else {
deferred.reject({
message: "Redirect to the default page."
});
alert("Please Login First!");
$location.path("/login");
}
return deferred.promise;
}
})();
And it doesn't work, I got error saying: defer is not defined, something like that. Then I used a factory to wrap that piece of logic:
(function() {
'use strict';
angular.module("appClubS", ["appClubS.userModule", "appClubS.productModule", "clubsServices", "ngRoute", "ui.bootstrap"])
.config(routeConfigurator);
angular.module("appClubS")
.controller("checkLoginCtrl", checkLoginController)
.factory('checkPermit', checkPermitFactory);
checkLoginController.$inject = ['$scope', '$rootScope', '$location', 'userFactory'];
routeConfigurator.$inject = ['$routeProvider', '$locationProvider', 'checkPermit'];
checkPermitFactory.$inject = ['$q', '$location', 'userFactory'];
function routeConfigurator($routeProvider, $locationProvider, checkPermit) {
$routeProvider.when("/home", {
templateUrl: "views/index.html"
});
// ...
// the routes that visitor cannot access before signing in
$routeProvider.when("/account-profile/my-redeem", {
templateUrl: "views/member_zone/my.redeem.html",
resolve: {
loggedin: function (checkPermit) {
return checkPermit.checklogin();
}
}
});
$routeProvider.when("/account-profile/my-survey", {
templateUrl: "views/member_zone/my.survey.html",
resolve: {
loggedin: function (checkPermit) {
return checkPermit.checklogin();
}
}
});
// ...
}
function checkPermitFactory($q, userFactory, $location) {
function checklogin() {
var deferred = $q.defer();
var logStatus = userFactory.loggedin();
if (logStatus) {
deferred.resolve({ message: "Proceed to change route." });
}
else {
deferred.reject({ message: "Redirect to the default page." });
alert("Please Login First!");
$location.path("/login");
}
return deferred.promise;
}
var factory = {
checklogin: checklogin
};
return factory;
}
})();
And I got error saying that it could not find checkPermit provider, when investigating this problem, I realized that you just cannot inject an dependency on an stance of factory to routeConfigurator, so here I am supposed to use checkPermitProvider instead.
I am confused now.
Any help is appreciated. Thanks.
thank you all for the replies.
In the end, I found I can get it working in this way:
(function() {
'use strict';
angular.module("appClubS", ["appClubS.userModule", "appClubS.productModule", "clubsServices", "ngRoute", "ui.bootstrap"])
.config(routeConfigurator);
angular.module("appClubS")
.controller("checkLoginCtrl", ['$q', '$location', 'userFactory', function checkPermitFactory($q, userFactory, $location) {
function checklogin() {
var deferred = $q.defer();
var logStatus = userFactory.loggedin();
if (logStatus) {
deferred.resolve({ message: "Proceed to change route." });
}
else {
deferred.reject({ message: "Redirect to the default page." });
alert("Please Login First!");
$location.path("/login");
}
return deferred.promise;
}
var factory = {
checklogin: checklogin
};
return factory;
}])
.factory('checkPermit', checkPermitFactory);
checkLoginController.$inject = ['$scope', '$rootScope', '$location', 'userFactory'];
routeConfigurator.$inject = ['$routeProvider', '$locationProvider', 'checkPermit'];
function routeConfigurator($routeProvider, $locationProvider, checkPermit) {
$routeProvider.when("/home", {
templateUrl: "views/index.html"
});
// ...
// the routes that visitor cannot access before signing in
$routeProvider.when("/account-profile/my-redeem", {
templateUrl: "views/member_zone/my.redeem.html",
resolve: {
loggedin: function (checkPermit) {
return checkPermit.checklogin();
}
}
});
$routeProvider.when("/account-profile/my-survey", {
templateUrl: "views/member_zone/my.survey.html",
resolve: {
loggedin: function (checkPermit) {
return checkPermit.checklogin();
}
}
});
// ...
}
})();
I used $inject property to specify the dependencies just because that was suggested in the section 'Manually Identify Dependencies' in this article: https://github.com/johnpapa/angularjs-styleguide#manually-identify-dependencies.
And honestly I don't quite understand how does $inject work exactly though; I just got the concerns behind that. So this problem has been solved, but I don't know the difference between the two ways of defining a controller and declaring there dependencies.

how to delay loading the page in route AngularJS?

I would like to before the advent of the home page if the user is not logged in is to move it to the login page.
At this moment Main page appears (half a second) and then loads the login page.
var app = angular.module("app", ["ngRoute", "ngAnimate"])
.constant('ACCESS_LEVELS', {
guest: 1,
user: 2,
admin: 3
});
app.config(["$routeProvider", "$locationProvider", "ACCESS_LEVELS", function($routeProvider, $locationProvider, ACCESS_LEVELS) {
$routeProvider
.when("/", {
template: "",
access_level: ACCESS_LEVELS.user
});
}]);
app.run(["$rootScope", "$window", "LoginService", function($rootScope, $window, LoginService) {
$rootScope.$on('$routeChangeStart', function(evt, next, curr) {
if(next.access_level !== undefined) {
LoginService.checkSession().then(function(response) {
$rootScope.isLoggedIn = response;
if(!response) {
$window.location.href = '/login.html';
}
}, function(error) {
$rootScope.isLoggedIn = error;
});
}
})
}]);
Is there a way to angular done without flash home page?
regards
You can use the ‘resolve’ property of the routeProvider.
From the docs:
resolve - An optional map of dependencies which should be >injected into the controller. If any of these dependencies are promises, the router will wait >for them all to be resolved or one to be rejected before the controller is instantiated.
https://docs.angularjs.org/api/ngRoute/provider/$routeProvider
So your routeProvider could look as follows, with the session promise specified as a dependency of your home route. You would then need to inject the session into the home controller.
$routeProvider
.when("/", {
template: "",
access_level: ACCESS_LEVELS.user,
controller: ‘homeCtrl’,
resolve: {
session: function(LoginService) {
return LoginService.checkSession();
}
}
});
A good blog post: http://blog.brunoscopelliti.com/show-route-only-after-all-promises-are-resolved
My current code:
in main app.js:
var app = angular.module("app", ["ngRoute", "ngAnimate", "ngResource"])
.constant('ACCESS_LEVELS', {
guest: 1,
user: 2,
admin: 3
});
besecure.config(["$routeProvider", "$locationProvider", "ACCESS_LEVELS", function($routeProvider, $locationProvider, ACCESS_LEVELS) {
$routeProvider
.when("/", {
template: "",
label: "Home",
access_level: ACCESS_LEVELS.user,
resolve: {
session: function(LoginService) {
return LoginService.checkSession();
}
}
});
}]);
app.run(["$rootScope", "$window", "$location", "LoginService", function($rootScope, $window, $location, LoginService) {
$rootScope.loadingView = false;
$rootScope.$on('$routeChangeStart', function(evt, curr, prev) {
if(curr.access_level !== undefined) {
if(curr.$$route && curr.$$route.resolve) {
$rootScope.loadingView = true;
} else {
$window.location.href = '/login.html';
}
}
})
}]);
Service:
app.factory("LoginService", function($resource, $q) {
var LoginService,
Login = $resource("/auth/login");
LoginService = {
checkSession: function() {
var deferred = $q.defer();
Login.get().$promise.then(function(response) {
deferred.resolve(response.result);
}, function(error) {
deferred.reject(false);
});
return deferred.promise;
}
};
return LoginService;
});
Service is OK.
and not work redirecting

AngularJS working with $location.path and ngRoute

I have this $location.path redirection:
myapp.controller('registerCtrl', function ($scope, $location, regService) {
$scope.register = function() {
$('#regbutton').prop('disabled','disabled');
regService.createUser($scope.email, $scope.password, function(id) {
if (id) {
$('#register').modal('hide');
$location.path('/account');
}
});
}
})
When the redirection occurs it redirects the user to http://myapp.com/#/account
Now I want to display a different template to show the user account. So I'm trying to use ngRoute but cannot get it to work properly..
myapp.config(['$routeProvider', '$locationProvider', '$provide',
function ($routeProvider, $locationProvider, $provide) {
console.log('in');
$provide.decorator('$sniffer', function($delegate) {
$delegate.history = false;
return $delegate;
});
$routeProvider.
when('/account', {
templateUrl: 'account.html',
resolve: {
// I will cause a 1 second delay
delay: function ($q, $timeout) {
console.log('in resolve');
var delay = $q.defer();
$timeout(delay.resolve, 1000);
return delay.promise;
}
}
});
$locationProvider
.html5Mode(true)
.hashPrefix('');
}]);
The route you should be using in the configuration when() function is /account

Resources