Related
I am using http-server package to run my angular js project. My directory structure is below:-
angulardemo/app/public/controller
angulardemo/app/public/app.js
angulardemo/app/public/index.html
angulardemo/app/public/view
ang my app.js file is
var app = angular.module('angulardemo', ['ngRoute', 'ngCookies'])
.constant('API_URL', 'http://127.0.0.1:8001')
.config(function ($routeProvider, $locationProvider, $httpProvider) {
$httpProvider.defaults.headers.common = {'Content-Type' : 'application/json'};
$httpProvider.defaults.headers.post = {};
$httpProvider.defaults.headers.put = {};
$httpProvider.defaults.headers.patch = {};
/**
*
* Checks for url access
*/
resolver = function (access){
return {
load: function($q, AuthService, $location){
if(access){
return true
}else{
if(AuthService.checkLogin()){
return true;
}
else{
$location.path("/login");
}
}
}
}
}
$routeProvider
.when('/', {
templateUrl : "/view/home.html",
controller : 'PagesController'
})
.when('/home', {
templateUrl : "/view/home.html",
controller : 'PagesController'
})
.when('/about', {
templateUrl : "/view/about.html",
controller : 'PagesController'
})
.when('/team', {
templateUrl : "/view/team.html",
controller : 'PagesController'
})
.when('/work', {
templateUrl : "/view/work.html",
controller : 'PagesController'
})
.when('/price', {
templateUrl : "/view/price.html",
controller : 'PagesController'
})
.when('/users/:user_type', {
templateUrl : "/view/developers.html",
controller : 'UsersController'
})
.when('/user/show/:id', {
templateUrl : "/view/user.details.html",
controller : 'UsersController'
})
.when('/contact', {
templateUrl : "/view/contact.html",
controller : 'PagesController'
})
.when('/register', {
controller: 'AuthController',
templateUrl: '/view/auth/register.html',
resolve:{
loggedIn: function(AuthService, $location){
if(!AuthService.checkLogin())
return true;
else
$location.path("/home");
}
}
})
.when('/login', {
controller: 'AuthController',
templateUrl: '/view/auth/login.html',
resolve:{
loggedIn: function(AuthService, $location){
if(!AuthService.checkLogin())
return true;
else
$location.path("/home");
}
}
})
.when('/dashboard', {
controller: 'DashboardController',
templateUrl: '/view/dashboard/index.html',
pageTitle: 'dashboard',
resolve:resolver(false)
})
.when('/users_personal/:id', {
controller: 'UsersController',
templateUrl: '/view/users/personal.html',
pageTitle: 'personal_details',
resolve:resolver(false)
})
.when('/users_edu/:id', {
controller: 'UsersController',
templateUrl: '/view/users/edu.html',
pageTitle: 'edu_details',
resolve:resolver(false)
})
.when('/users_contact/:id', {
controller: 'UsersController',
templateUrl: '/view/users/contact.html',
pageTitle: 'contact_details',
resolve:resolver(false)
})
.when('/users_other/:id', {
controller: 'UsersController',
templateUrl: '/view/users/other.html',
pageTitle: 'other',
resolve:resolver(false)
})
.when('/logout', {
resolve : {
logout: function ($routeParams, $location, $http, API_URL){
$http.get(API_URL + "/api/auth/logout").success(function (response) {
if(response === "OK"){
localStorage.removeItem('auth');
$location.path('/login').replace();
}
})
}
}
})
.otherwise({
redirectTo: '/',
});
$locationProvider.html5Mode({
enabled: true,
requireBase: false
}).hashPrefix('*');
}).run(['$http', '$cookies', function($http, $cookies) {
$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
}]);
when I am running project using "http-server" with in the app directory command I got url as http://127.0.0.1:8080
http://192.168.10.137:8080
all the pages are working fine but when I am refreshing the page I am getting This 127.0.0.1 page can’t be found
No web page was found for the web address: http://127.0.0.1:8080/team
HTTP ERROR 404
So can anyone please tell that what wrong thing is here. and provide the solution.
See the directory structure in git hub:-
https://github.com/sanjaysamant/angulardemo/tree/local/app
Angular js files are in the public directory
Thanks
Please see terminal screen shot:
Whenever you are on a sub-URL such as /team and you refresh the page, the Node-Server looks for a HTML-File that is in the folder team on your server, which is not what you want. You need the server to redirect all those URL's to your index.html so that it loads the Angular Application, which can then properly initialize the correct page.
You can try the following in your server.js file:
//routes
app.use('/api/auth', require('./controllers/auth/auth.controller'));
app.use('/api/users', require('./controllers/users/users.controller'));
app.use('/api/user/', require('./controllers/users/users.controller'));
// Redirect unmatched routes (All specific routes such as /api/* need to be before this call)
app.use(redirectUnmatched);
function redirectUnmatched(req, res) {
res.redirect("/");
}
What #Chnoch suggested is correct, however I want to give you a different approach.
app.get('*', function(req, res)
{
res.send('/path/to/index.html');
});
Because all requests for a page will be a GET requests, you don't need to specify POST, and with this approach it will preserve the current URL you are on (eg. if you were on http://127.0.0.1:8080/team you will refresh and still be on /team), wheras #Chnoch's approach will always redirect you back to http://127.0.0.1:8080/.
What this will do is for any request that can't be resolved by the Node server, it will just render plain index page that can then be handled by Angular's ngRoute to display templates (you can also use templating engines like EJS or Pug with this, just replace the res.send with the rendering function).
Just make sure that the above code is after ALL other routes you want to be resolved by the Node server (eg. your API etc.) so it doesn't interfere with routes after it, since this is a catch all route.
I need to restrict the user from redirect and need to login only with authentication.
I tried but I can redirect to login page using back button and again come to same page using forward button. Even I can go to the required page using URL without login.
My code :
config.$inject = ['$routeProvider', '$locationProvider'];
function config($routeProvider, $locationProvider ) {
$routeProvider
.when('/login', {
controller: 'LoginController',
templateUrl: 'view/login.view.html',
controllerAs: 'vm'
})
.when('/profileData', {
controller: 'profileDataController',
templateUrl: 'view/profiledata.view.html',
controllerAs :'vm'
})
.when('/questionBank', {
controller: 'questionbankController',
templateUrl: 'view/questionbank.view.html',
controllerAs: 'vm'
})
.when('/dashboard', {
// controller: 'PersonalInfoController',
templateUrl: 'view/dashboard.view.html',
controllerAs:'vm'
})
.otherwise({ redirectTo: '/login' });
}
run.$inject = ['$rootScope', '$location', '$cookieStore', '$http'];
function run($rootScope, $location, $cookieStore, $http) {
// keep user logged in after page refresh
$rootScope.globals = $cookieStore.get('globals') || {};
if ($rootScope.globals.currentUser) {
$http.defaults.headers.common['Authorization'] = 'Basic ' + $rootScope.globals.currentUser.authdata; // jshint ignore:line
}
$rootScope.$on('$locationChangeStart', function (event, next, current) {
//redirect to login page if not logged in and trying to access a restricted page
var restrictedPage = $.inArray($location.path(), ['/dashboard','/questionBank', '/profileData']) === -1;
/* var a = $location.$$absUrl.split('#')[1];
var patt = new RegExp(a);
var res = patt.test(restrictedPage); */
var loggedIn = $rootScope.globals.currentUser;
if (restrictedPage && !loggedIn) {
$location.path('/login');
}
});
}
use this :based on response from server
.when('/login', {
controller: 'LoginController',
templateUrl: 'view/login.view.html',
resolve:{
logincheck: checklogedin
})
/ resolve function for user....
var checklogedin = function($q ,$http,$location)
{
var deferred =$q.defer();
$http.get('/loggedin').success(function(user){
if (user.staus==true)
{
//goo
deferred.resolve();
}
else
{
deferred.reject();
$location.url('/login');
}
});
return deferred.promise
};
Based on the code that you have provided, I can't tell 100% what is going on in your code. But... you could always try to use the resolve property on each route that you don't want to allow access without authentication. Here is what that would look like for questionBank:
.when('/questionBank', {
controller: 'questionbankController',
templateUrl: 'view/questionbank.view.html',
controllerAs: 'vm',
resolve: {
auth: function(AuthService, $q){
if(AuthService.isAuthenticated()) return $q.resolve();
return $q.reject();
}
}
})
Each property of the resolve object should return a promise, and if that resolves... the route change works. If it rejects... the route change is not allowed. If the promise never resolves, you are screwed, so make sure it resolves or it will never do the route.
This isn't the only way to try what you are saying. It is A way of trying it.
You can also add event listener on your $scope and prevent moving in case of unauthenticated user.
$scope.$on('$locationChangeStart', function (event, next, current) {
if (!is_logged_in) {
event.preventDefault();
}
});
In my code I have two main controllers LoginCtrl and AppCtrl, and all other controllers are nested within AppCtrl. Then in AppCtrl I have this code, which will check for logged user.
if (localStorageService.get('authToken') === null) {
$state.go('login', {locale: CONFIG.defaultLang});
} else if (!userService.isLoggedIn()) {
tokenStorage.setAuthToken(localStorageService.get('authToken'));
userService.setIdentity(JSON.parse(localStorageService.get('user')));
}
As you can see I store auth token from server in local storage. When page loades this code will be executed and if you are not logged in you will be redirected. And because all other application controllers are nested within AppCtrl this code will be executed every time.
For more info about nested controllers try for example this article - https://rclayton.silvrback.com/parent-child-controller-communication
Ok this question is a bit complex to explain.
I use ng-view, $routeProvider and $routeChangeStart to make an authorization login/signup system.
my js code is here
app.config(['$routeProvider',
function ($routeProvider) {
$routeProvider.
when('/login', {
title: 'Login',
templateUrl: 'authorization/login.html',
controller: 'authCtrl'
})
.when('/profile', {
title: 'Profile',
templateUrl: 'authorization/profile/index.html',
controller: 'authCtrl'
})
.when('/myaccount', {
title: 'MyAccount',
templateUrl: 'authorization/profile/account/index.html',
controller: 'authCtrl'
})
.otherwise({
redirectTo: '/login'
});
}
])
.run(['$rootScope', '$location', 'loginService', function ($rootScope, $location, loginService) {
var routeLogin = ['/login', '/signup']; //pages required before login
$rootScope.$on("$routeChangeStart", function (event, next, current) {
$rootScope.authenticated = false;
loginService.get('session').then(function (results) {
if (results.cid) {
$rootScope.authenticated = true;
$rootScope.cid = results.cid;
$rootScope.personal_name = results.personal_name;
$rootScope.personal_email = results.personal_email;
if(routeLogin.indexOf($location.path()) != -1) {
$location.path('/profile');
}
} else {
if (routeLogin.indexOf($location.path()) == -1) {
$location.path("/login");
}
}
});
});
}]);
After login, I want to use <a href="#/profile/account"> or ng-href in the profile page to direct to my account page, which is the 'myaccount' in $routeProvider.
However, after I click the link, the script always uses the 'otherwise' option in the $routeProvider and redirect me back the profile page (because I have logged in, so it redirect to the login page and then redirect to the profile page).
And if I don't use otherwise, the authorization system won't work, and give me a blank page (unless if I create an .htaccess file but I am not sure if it will work or I should do that).
Could anyone tells me why is that and how to fix it?
Thank you.
I'm working with routes :
App.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/home', {
templateUrl: 'orders/list',
controller: OrderController
});
$routeProvider.when('/editOrder', {
templateUrl: 'addOrder/editOrder',
controller: ActionController
});
$routeProvider.otherwise({redirectTo: '/home'});
I want to navigate to the edit page only when a button is clicked, but this definition allows access via url from browser also. Is it possible to disable access via url ?
You can use $routeChangeStart event to implement custom logic on route to be changed and veto navigation depending on some condition/permission. In the following example you can navigate to /edit route only if you have granted permissions, which you can grant or revoke using PermissionsService service. In the following example you can try to navigate via direct link and see that you are redirected to default route, and when you click Edit button you are redirected to the relevant route. Also, if you are on /edit route and make browser back and forward, you can notice that you can't go back to /edit route.
HTML
Home
Edit
<div ng-view></div>
<button ng-click="edit()">Edit</button>
JavaScript
angular.module('app', ['ngRoute']).
config(['$routeProvider', function($routeProvider){
$routeProvider.when('/home', {
templateUrl: 'list.html',
controller: 'OrderController'
});
$routeProvider.when('/edit', {
templateUrl: 'edit.html',
controller: 'ActionController'
});
$routeProvider.otherwise({redirectTo: '/home'});
}]).
run(['$rootScope', '$location', 'PermissionsService', function($rootScope, $location, PermissionsService) {
$rootScope.edit = function() {
PermissionsService.setPermission('edit', true);
$location.path('/edit');
};
$rootScope.$on("$routeChangeStart", function(event, next, current) {
if (next.templateUrl === "edit.html") {
if(!PermissionsService.getPermission('edit')) {
$location.path('/');
}
PermissionsService.setPermission('edit', false);
}
});
}]).
service('PermissionsService', [function() {
var permissions = {
edit: false
};
this.setPermission = function(permission, value) {
permissions[permission] = value;
}
this.getPermission = function(permission) {
return permissions[permission] || false;
}
}]).
controller('OrderController', [function() {}]).
controller('ActionController', [function() {}]);
Live example here.
You can use the resolve property and set some variable on an external service:
App.factory('editMode', function(){
var editMode = false;
return {
getEditMode: function(){ return editMode; },
setEditMode: function(edit) { editMode = edit; }
}
}
And then on the route:
$routeProvider.when('/editOrder', {
templateUrl: 'addOrder/editOrder',
controller: ActionController,
resolve: function(editMode){
if(!editMode.getEditMode()) {
$location.path( "/" );
}
}
});
Using the $rootScope.$on('$routeChangeStart', function(event, next, current), I'm redirecting to the signin page if the route requires authentication. That works perfectly.
How do I redirect back to the intended route though after signing in?
This is a simplified version of what's working for me:
app = angular.module('ngApp', []).config(function ($routeProvider) {
$routeProvider
.when('/dashboard', {
templateUrl: 'dashboard.html',
controller: 'dashboardController',
loginRequired: true //
})
.when('/login', {
templateUrl: 'login.html',
controller: 'loginController'
})
.otherwise({redirectTo: '/login'})
});
Then in the application's run block:
app.run(function ($location, $rootScope) {
var postLogInRoute;
$rootScope.$on('$routeChangeStart', function (event, nextRoute, currentRoute) {
//if login required and you're logged out, capture the current path
if (nextRoute.loginRequired && Account.loggedOut()) {
postLogInRoute = $location.path();
$location.path('/login').replace();
} else if (postLogInRoute && Account.loggedIn()) {
//once logged in, redirect to the last route and reset it
$location.path(postLogInRoute).replace();
postLogInRoute = null;
}
});
});
Here is an example of how I am doing it, hope it helps:
On the route provider, first set up the public access somehow:
// Just a demo on how the routes were set up to determine public access
angular.module('ngApp', []).config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller : 'MainController',
})
.when('/login', {
templateUrl : 'views/login.html',
controller : 'LoginController',
publicAccess : true // This is used in $routeChangeStart later
});
});
});
Then:
$rootScope.$on('$routeChangeStart', function(event, next, current) {
var publicAccess = next.publicAccess || false;
// This is just a service I made, this is how I check logged in status
// AuthenticationService.check() returns a promise
AuthenticationService.check().then(function() {
// As this is a promise, this block signals that the user is logged in
// If the page is marked as public access, then redirect to private area
if (publicAccess)
$location.path('/').replace();
}, function() {
// Since this segment of the promise signals that the user is not
// logged in, if the page is not publicly accessible, redirect to login
if (!publicAccess)
$location.path('/login').replace();
});
});
The following answer is from the OP.
Here's how I solved it:
I added this event broadcast into the $routeChangeStart
$rootScope.$on('$routeChangeStart', function(event, next, current) {
if (next.authRequired) {
var deferred = $q.defer(),
_token = mainConfig.csrfToken;
security.getCurrentUser(true, _token).success(function (data, status, headers, config) {
if(status == 200) {
// set the local scope variables
next.scope.isAuthenticated = true;
next.scope.user = security.currentUser;
// Broadcast out to each of the listeners
$rootScope.$broadcast('currentUserAuthenticated');
// Any other response requires a signin. Redirect.
} else {
next.scope.isAuthenticated = false;
next.scope.user = null;
$rootScope.$broadcast('authenticationRequired', $location.url());
$location.path('/signin');
}
});
}
});
Then in my security factory, I listened for the event and stored the location, like so:
$rootScope.$on('authenticationRequired', function(event, callingRoute) {
redirectRoute = callingRoute;
});