I am trying to restrict access to some pages within the public directory using Angular routing.
.when('/adminprofile', {
templateUrl: '../partials/adminprofile.html',
access: {restricted: true}
})
I am trying to read what I believe is a property called access which I declared, called access
myApp.run(function ($rootScope, $location, $route, AuthService) {
$rootScope.$on('$routeChangeStart',
function (event, next, current) {
AuthService.getUserStatus()
.then(function(){
if (next.access.restricted && !AuthService.isLoggedIn()){
$location.path('/login');
$route.reload();
}
});
});
});
But what I get is this error:
TypeError: next.access is undefined
How can I read the property or how can i achieve this in a better way?, Thanks
EDIT :
According to suggestion, I have changed the code and it looks as it follows:
var myApp = angular.module('myApp', ['ngRoute']);
myApp.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: '../partials/home.html',
resolve: {
access: false
}
})
.when('/home', {
templateUrl: '../partials/home.html',
resolve: {
access: false
}
})
.when('/login', {
templateUrl: '../partials/login.html',
controller: 'loginController',
resolve: {
access: false
}
})
.when('/logout', {
controller: 'logoutController',
resolve: {
access: false
}
})
.when('/register', {
templateUrl: '../partials/register.html',
controller: 'registerController',
resolve: {
access: false
}
})
.when('/adminprofile', {
templateUrl: '../partials/adminprofile.html',
resolve: {
access: true
}
})
.otherwise({
redirectTo: '/'
});
});
And I have my run function:
myApp.run(function ($rootScope, $location, $route, AuthService) {
debugger;
$rootScope.$on('$routeChangeStart',
function (event, next, current) {
AuthService.getUserStatus()
.then(function(){
if (next.resolve.access && !AuthService.isLoggedIn()){
$location.path('/login');
$route.reload();
} else{
$location.path($route.current.originalPath);
}
});
});
});
Now I can see the value of access:
next.resolve.access
but is not displaying anything, I run in debug and can see that actually is going through the $routeChangeStart callback , whyyyyy?? helppppp!
ok fellas, is done, this is the right way to do it:
var myApp = angular.module('myApp', ['ngRoute']);
myApp.config(function ($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: '../partials/home.html',
resolve: {
access: function() {
return false;
}
}
})
.when('/home', {
templateUrl: '../partials/home.html',
resolve: {
access: function() {
return false;
}
}
})
.when('/login', {
templateUrl: '../partials/login.html',
controller: 'loginController',
resolve: {
access: function() {
return false;
}
}
})
.when('/logout', {
controller: 'logoutController',
resolve: {
access: function() {
return false;
}
}
})
.when('/register', {
templateUrl: '../partials/register.html',
controller: 'registerController',
resolve: {
access: function() {
return false;
}
}
})
.when('/adminprofile', {
templateUrl: '../partials/adminprofile.html',
resolve: {
access: function() {
return true;
}
}
})
.otherwise({
redirectTo: '/'
});
});
myApp.run(function ($rootScope, $location, $route, AuthService) {
debugger;
$rootScope.$on('$routeChangeStart',
function (event, next, current) {
AuthService.getUserStatus()
.then(function(){
if (next.resolve.access && !AuthService.isLoggedIn()){
$location.path('/login');
$route.reload();
}
});
});
});
resolve has to be a function
Resolve will open your route with a resolved variable (that can be injected into controller) as soon as it gets value (instantly or when returned promise will be resolved)
as it was not returning a value, the router seems to be stuck waiting for a value to resolve.
Related
In my main module i have used ui-bootstrap modal for checking login authentication.From run block i have called to loginModal service but it is giving Error
TypeError: loginModal is not a function
angular.module('myApp', ['ui.router', 'ui.bootstrap', 'loginServices','leaveServices']). config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise('/home');
$stateProvider.
state('home', {
url:'/home',
data: {
requireLogin: false
},
views: {
'': {
templateUrl: 'partials/templates/assets/home.html'
}
}
}).
state('home.about', {
url: '/about',
templateUrl: 'partials/templates/assets/about.html'
}).
state('home.contact', {
url: '/contact',
templateUrl: 'partials/templates/assets/contactUs.html'
}).
state('/login', {
url: '/login',
data: {
requireLogin: false
},
templateUrl: 'partials/login.html',
controller: loginUserController
}).
state('/register', {
url:'/register',
data: {
requireLogin: false
},
templateUrl: 'partials/registerUser.html',
controller: registerController
}).
state('/getAllUsers', {
url: '/getAllUsers',
data: {
requireLogin: false
},
templateUrl: 'partials/getAllUsers.html',
controller: getUsersController
}).
state('/updateUser', {
url : '/updateUser/:id/:name',
data: {
requireLogin: true
},
params: {'id':null, 'name':null},
templateUrl: 'partials/updateUser.html',
controller: updateUserController
}).
state('/userLeave', {
url : '/userLeave:name',
data: {
requireLogin: true
},
params: {'name': null},
templateUrl: 'partials/userLeave.html',
controller: userLeaveController
}).
state('/leaveRequest', {
url : '/leaveRequest',
data: {
requireLogin: true
},
templateUrl: 'partials/leaveRequest.html'
});
}])
.run(function ($rootScope, $state, loginModal) {
$rootScope.$on('$stateChangeStart', function (event, toState, toParams) {
var requireLogin = toState.data.requireLogin;
console.log('going to state '+toState.name);
if (requireLogin && typeof $rootScope.currentUser === 'undefined') {
event.preventDefault();
loginModal().then(function () {
return $state.go(toState.name, toParams);
})
.catch(function () {
return $state.go('/login');
});
}
});
})
.factory('loginModal', function ($modal, $rootScope) {
function assignCurrentUser (user) {
$rootScope.currentUser = user;
return user;
}
return function() {
var instance = $modal.open({
templateUrl: 'partials/login.html',
controller: loginUserController
});
return instance.result.then(assignCurrentUser);
}
});
here login controller
loginUserController.$inject = ['$scope','$http', 'loginFactory', '$location', '$state'];
function loginUserController($scope,$http,loginFactory,$location, $state){
$scope.validateLogin = function(name,password){
$http.get("http://localhost:3010/validateLogin?userName="+name+"&password="+password)
.then(function(response) {
if(response.data.length != 0) {
console.log("logged user data is "+JSON.stringify(response.data));
$state.transitionTo('/userLeave', {name: name});
// $scope.$close(response);
}
else
$scope.inValidUser = 'Invalid User';
});
};
$scope.cancel = $scope.$dismiss;
}
Could be because you're using an Angular service which expects a constructor which in turn, should not be returning something.
Try changing to a factory, eg
.factory('loginModal', ...
Right now i am making an AngularJS+UI router install application. But i have a problem, the problem is, that i want to disable access to the views, associated with the install application. I want to do it in resolve in the state config.
But the problem is i need to get the data from a RESTful API, whether the application is installed or not. I tried making the function, but it loaded the state before the $http.get request was finished.
Here was my code for the resolve function:
(function() {
var app = angular.module('states', []);
app.run(['$rootScope', '$http', function($rootScope, $http) {
$rootScope.$on('$stateChangeStart', function() {
$http.get('/api/v1/getSetupStatus').success(function(res) {
$rootScope.setupdb = res.db_setup;
$rootScope.setupuser = res.user_setup;
});
});
}]);
app.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/404");
$stateProvider.state('db-install', {
url: "/install/db",
templateUrl: 'admin/js/partials/db-install.html',
controller: 'DBController',
resolve: {
data: function($q, $state, $timeout, $rootScope) {
var setupStatus = $rootScope.setupdb;
var deferred = $q.defer();
$timeout(function() {
if (setupStatus === true) {
$state.go('setup-done');
deferred.reject();
} else {
deferred.resolve();
}
});
return deferred.promise;
}
}
})
.state('user-registration', {
url: "/install/user-registration",
templateUrl: "admin/js/partials/user-registration.html",
controller: "RegisterController"
})
.state('setup-done', {
url: "/install/setup-done",
templateUrl: "admin/js/partials/setup-done.html"
})
.state('404', {
url: "/404",
templateUrl: "admin/js/partials/404.html"
});
}]);
})();
EDIT:
Here is what my ajax call returns:
Try this way:
$stateProvider.state('db-install', {
url: "/install/db",
templateUrl: 'admin/js/partials/db-install.html',
controller: 'DBController',
resolve: {
setupStatus: function($q, $state, $http) {
return $http.get('/api/v1/getSetupStatus').then(function(res) {
if (res.db_setup === true) {
$state.go('setup-done');
return $q.reject();
}
return res;
});
}
}
})
Then inject setupStatus in controller:
.state('setup-done', {
url: "/install/setup-done",
templateUrl: "admin/js/partials/setup-done.html",
controller: ['$scope', 'setupStatus', function ($scope, setupStatus) {
$scope.setupdb = setupStatus.db_setup;
$scope.setupuser = setupStatus.user_setup;
}]
})
I want to make my views show only after the initial data is fetched and i am trying to accomplish this with a route resolve, but i can't get it to work. What am i doing wrong? Also my angular skills are a bit shabby so i aplogize in advance if my question is dumb.
Application.js :
var Application = angular.module('ReporterApplication', ['ngRoute']);
Application.config(['$routeProvider', '$interpolateProvider',
function($routeProvider, $interpolateProvider) {
$interpolateProvider.startSymbol('<%');
$interpolateProvider.endSymbol('%>');
$routeProvider
.when('/packing/scan.html', {
templateUrl: 'packing/scan.html',
controller: 'PackingScanController',
resolve: {
initData : Application.PackingScanInit()
}
})
.when('/packing/stats.html', {
templateUrl: 'packing/stats.html',
controller: 'PackingStatisticsController'
})
etc
and here is my Scan.js file :
Application.PackingScanInit = function ($q,$timeout,$http) {
var serverData = "";
$http.get('/packing/scan.action')
.success(function(data){
serverData = data;
})
.error(function(data){
serverData = data;
});
return serverData;
}
Application.controller('PackingScanController', ['initData', '$scope', '$http', function(initData, $scope, $http) {
var packer = this;
// Message log model
packer.messageLog = [{
status : "",
message : null
}];
the files are included in this order.
service are singletons means there are initialized only one but time but if you simply return from service it will be called one time but if you return a function from service it will be called again and again .See Below Sample for working.
var app = angular.module('ajay.singhApp', [])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/view1', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
resolve: {
myVar: function (repoService) {
return repoService.getItems().then(function (response) {
return response.data;
});
}
}
})
.when('/view2', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.otherwise({
redirectTo: '/view1'
});
}]);
app.factory('repoService', function ($http) {
return {
getItems: function () {
return $http.get('TextFile.txt');
}
};
});
Try this:
Application.PackingScanInit = function ($q,$timeout,$http) {
return $http.get('/packing/scan.action')
.success(function(data){
return data;
})
.error(function(data){
return data;
});
}
Also you have to adjust your resolve to this:
resolve: {
initData : Application.PackingScanInit
}
Here is a specific working example:
(function() {
angular.module('app',['ngRoute']);
function TestCtrl($scope, initData) {
$scope.value = initData;
}
angular.module('app').config(function($routeProvider) {
$routeProvider.otherwise({
template: '`<p>Dude {{value}}</p>`',
controller: TestCtrl,
resolve: {
initData: function($http) {
return $http.get('test.json') //change to test-e.json to test error case
.then(function(resp) {
return resp.data.value; //success response
}, function() {
return 'Not Found'; // error response
});
}
}
});
});
})();
http://plnkr.co/edit/SPR3jLshcpafrALr4qZN?p=preview
I am looking at building a clientside authentication for my angular app. The routing looks like this:
var app = angular.module('app',['ngRoute']);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/customers', {
controller: 'CustomersController',
templateUrl: 'customers.html',
secure: true
})
.when('/login/:redirect*?', {
controller: 'LoginController',
templateUrl: 'login.html'
})
.when('/testing', {
controller: 'TestController',
templateUrl: 'testing.html' })
.otherwise({ redirectTo: '/customers' });
}]);
When I click on the login link it wont let me go to the login page?
See also this plunkr: http://plnkr.co/edit/TVSnCp8AtBKVfcYdWvN2?p=preview
Please update the app.js
(function () {
var app = angular.module('app',['ngRoute']);
app.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/customers', {
controller: 'CustomersController',
templateUrl: 'customers.html',
secure: false
})
.when('/login', {
controller: 'LoginController',
templateUrl: 'login.html'
})
.when('/testing', {
controller: 'TestController',
templateUrl: 'testing.html' })
.otherwise({ redirectTo: '/customers' });
}]);
app.run([ '$rootScope', '$location', 'authService',
function ( $rootScope, $location, authService) {
$rootScope.$on("$routeChangeStart", function (event, next, current) {
if (next && next.$$route && next.$$route.secure) {
if (!authService.user.isAuthenticated) {
authService.redirectToLogin();
}
}
});
}]);
}());
Put the case I've got a route like
.config(function (CONFIG,$routeProvider) {
$routeProvider
.when('/', {
templateUrl: CONFIG.site.path_views + '/index/index.html',
controller: 'IndexCtrl'
})
.when('/contestant/create', {
templateUrl: CONFIG.site.path_views + '/contestant/create.html',
controller: 'ContestantCreateCtrl'
})
.when('/contestant/thanks', {
templateUrl: CONFIG.site.path_views + '/contestant/thanks.html',
controller: 'ContestantThanksCtrl'
})
.when('/product', {
templateUrl: CONFIG.site.path_views + '/product/index.html',
controller: 'ProductCtrl'
})
.when('/prize', {
templateUrl: CONFIG.site.path_views + '/prize/index.html',
controller: 'PrizeCtrl'
})
.otherwise({
redirectTo: '/'
});
})
I'd like to deny access or simply redirect the user
to /contestant/create if he/she has filled in the form
but I don't find a way :(
app.run( function(VisitedRoutes) {
VisitedRoutes.init();
};
app.factory('VisitedRoutes', function($rootScope,$location) {
var routes = [];
return {
add : function(){
routes.push($location.path());
},
all:function(){
return _.uniq(routes);
},
hasRoute:function(value){
return _.indexOf(this.all(), value)
},
init:function(){
var that = this;
$rootScope.$on('$routeChangeSuccess', function (scope, next, current) {
that.add();
});
}
}
});
app.controller('ContestantCreateCtrl',function($scope,$location,VisitedRoutes) {
if(VisitedRoutes.hasRoute('/contestant/thanks') !== -1){
$location.path('/');
}
});
credit to #Jesus Rodriguez :)