2

I would like to have two home pages, the first would be for users who have not logged in and the second for users that are logged in.

This is my current set up:

.config(function ($stateProvider, $urlRouterProvider, $locationProvider, $httpProvider) {
    $urlRouterProvider
      .otherwise('/');

    $locationProvider.html5Mode(true);
    $httpProvider.interceptors.push('authInterceptor');
  })

  .factory('authInterceptor', function ($rootScope, $q, $cookieStore, $location) {
    return {
      // Add authorization token to headers
      request: function (config) {
        config.headers = config.headers || {};
        if ($cookieStore.get('token')) {
          config.headers.Authorization = 'Bearer ' + $cookieStore.get('token');
        }
        return config;
      },

      // Intercept 401s and redirect you to login
      responseError: function(response) {
        if(response.status === 401) {
          $location.path('/login');
          // remove any stale tokens
          $cookieStore.remove('token');
          return $q.reject(response);
        }
        else {
          return $q.reject(response);
        }
      }
    };
  })

  .run(function ($rootScope, $location, Auth) {
    // Redirect to login if route requires auth and you're not logged in
    $rootScope.$on('$stateChangeStart', function (event, next) {
      if (next.authenticate && !Auth.isLoggedIn()) {
        $location.path('/login');
      }
    });
  });
.config(function ($stateProvider) {
        $stateProvider
          .state('main', {
            url: '/',
            templateUrl: 'app/main/main.html',
            controller: 'MainCtrl',
            title: 'Home',
            mainClass: 'home',
            headerSearch: true
          });
      });

How could I reconfigure this so I could do something like the following:

.config(function ($stateProvider) {
    $stateProvider
      .state('welcome', {
        url: '/',
        templateUrl: 'app/welcome/welcome.html',
        controller: 'WelcomeCtrl',
        title: 'Welcome',
        mainClass: 'welcome',
        isLoggedIn: false
      });
     $stateProvider
      .state('main', {
        url: '/',
        templateUrl: 'app/main/main.html',
        controller: 'MainCtrl',
        title: 'Home',
        mainClass: 'home',
        isLoggedIn: true
      });
  });
2
  • I think you should refer to this Commented Aug 12, 2014 at 11:38
  • There is also module ui-router for this Commented Aug 12, 2014 at 11:39

4 Answers 4

5

Just wanted to show, how we can manage authentication driven access to states. Based on this answer and its plunker, we can enrich each state (which should be accessible only for authenticated users) with a data setting, explained here: Attach Custom Data to State Objects (cite:)

You can attach custom data to the state object (we recommend using a data property to avoid conflicts)...

So let's have some states with public access:

// SEE no explicit data defined
.state('public',{
    url : '/public',
    template : '<div>public</div>',
})
// the log-on screen
.state('login',{
    url : '/login',
    templateUrl : 'tpl.login.html',
    controller : 'UserCtrl',
})
... 

And some with private access:

// DATA is used - saying I need authentication
.state('some',{
    url : '/some',
    template : '<div>some</div>',
    data : {requiresLogin : true }, // HERE
})
.state('other',{
    url : '/other',
    template : '<div>other</div>',
    data : {requiresLogin : true }, // HERE
})

And this could be hooked on on the state change:

.run(['$rootScope', '$state', 'User', function($rootScope, $state, User)
{

  $rootScope.$on('$stateChangeStart'
    , function(event, toState, toParams, fromState, fromParams) {

    var isAuthenticationRequired =  toState.data 
          && toState.data.requiresLogin 
          && !User.isLoggedIn
      ;

    if(isAuthenticationRequired)
    {
      event.preventDefault();
      $state.go('login');
    }
  });
}])

See all that in action here

There is similar Q & A were I try to show the concept of redirecting Authenticated and Not Authenticated user:

maybe that could help to get some idea, how we can use ui-router, and its event '$stateChangeStart' to hook on our decision manager - and its forced redirecting...

Sign up to request clarification or add additional context in comments.

Comments

2

the code should be something like this

     $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState)                { //, fromParams
       console.log(toState.name + "," + fromState.name);
        if(fromState.name === "") {
          if (Auth.isLoggedIn()) {
              $state.go('welcome');
               event.preventDefault();
          } else {
            $state.go('home');
               event.preventDefault();
        } else {
           if (toState.authenticate && !Auth.isLoggedIn()) {
               $toState.go('login');
               event.preventDefault();
           }
        }
    }

so if user entering the application, then if he is logged in take him to welcome else take him to home.

once he is inside, then if he hits some route which needs auth.. then redirect him to login page..

sorry if i did not understood you requirement fully...

21 Comments

I gave this a try but all I got was an error saying stateChangeStart doesn't exist. I removed it so just using $rootScope.$on('$stateChangeStart'); and that didn't throw an error but instead it just didn't work.
Am I meant to put this inside .run(function ($rootScope, $location, Auth) {?
I found the missing colon but now I get ReferenceError: $state is not defined
Ok, the now gives TypeError: undefined is not a function
have you inject your auth service?? can you setup plunker, ??
|
1
.config(function ($stateProvider,$rootScope) {
$stateProvider
  .state('welcome', {
    url: '/',
    templateUrl: 'app/welcome/welcome.html',
    controller: 'WelcomeCtrl',
    onEnter: function() {
      if (userIsLoggedIn()) {
         $stateProvider.go('home');
      }
  });

});

2 Comments

I can't seem to get this working. It still just defaults to 'home'
I found that a brace was missing so I get the following error: Uncaught Error: [$injector:modulerr] Failed to instantiate module cbuiRouterApp due to: Error: [$injector:unpr] Unknown provider: $rootScope
0

I had problem like this and I solved it like this

 .run(function ($rootScope, $location, AuthService) {

        // start showing PRELOADER because we doing async call and we dont know when it will be resolved/rej
        AuthService.checkLoginStatus().then(
            (resp) => {
                // fire logged in user event
                $rootScope.$broadcast('userLogged',resp);
                $location.path(YourHomePageUrl);

            },
            (err)=> {  
                // Check that the user is not authorized redirect to login page                  
                    $location.path(loginURL);
                }
            }).finally(
            ()=> {
                // finnaly Set a watch on the $routeChangeStart
                /// Hide PRELOADER
                $rootScope.$on('$routeChangeStart',
                    function (evt, next, curr) {
                      if (!AuthService.isLoggedIn()) {
                                $location.path(art7.API.loginURL);
                            }

                    });
            }
        )


    });

and im not using interceptor for handling 401 not authorized errors, thats my solution

1 Comment

Its in typescript , AuthService was my service for authentication

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.