2014-11-13 17 views
17

Ho un'app AngularJS a pagina singola, che funziona con Express, node.js e MongoDB tramite Mongoose. Utilizzo di Passport per la gestione/autenticazione degli utenti.AngularJS - mostra/nascondi gli oggetti nav se l'utente è connesso

Mi piacerebbe che gli elementi della barra di navigazione cambino in base al fatto che un utente abbia effettuato l'accesso o meno. Sto avendo difficoltà a capire come implementarlo.

faccio a sapere se un utente è connesso tramite una http richiesta:

server.js

app.get('/checklogin',function(req,res){ 
    if (req.user) 
    res.send(true); 
    else 
    res.send(false); 

Sul front-end, ho un NavController chiamare questo utilizzando il servizio di angolare $http:

NavController.js

0.123.

Nel mio nav, sto usando ng-show e ng-hide per determinare quali selezioni dovrebbero essere visibili. Sto anche attivando la funzione isLoggedIn() quando l'utente fa clic sugli oggetti nav, controllando se l'utente ha effettuato l'accesso durante ciascun clic.

index.html

<nav class="navbar navbar-inverse" role="navigation"> 
    <div class="navbar-header"> 
    <a class="navbar-brand" href="/">Home</a> 
    </div> 
    <ul class="nav navbar-nav"> 
    <li ng-hide="loggedIn" ng-click="isLoggedIn()"> 
     <a href="/login">Login</a> 
    </li> 
    <li ng-hide="loggedIn" ng-click="isLoggedIn()"> 
     <a href="/signup">Sign up</a> 
    </li> 
    <li ng-show="loggedIn" ng-click="logOut(); isLoggedIn()"> 
     <a href="#">Log out</a> 
    </li> 
    </ul> 
</nav> 

Problema

Ci sono altri posti nella mia app in cui l'utente può accedere in/out, al di fuori del campo di applicazione della NavController. Ad esempio, c'è un pulsante di accesso nella pagina di accesso, che corrisponde al LoginController. Immagino che ci sia un modo migliore per implementarlo su tutta la mia app.

Come posso "guardare" se req.user è true sul back-end e i miei elementi di navigazione rispondono di conseguenza?

risposta

11

è possibile utilizzare $rootScope per condividere informazioni attraverso l'intera applicazione:

.controller('NavController',function($scope,$http, $rootScope) { 

    $scope.isLoggedIn = function() { 

     $http.get('/checklogin') 
     .success(function(data) { 
      console.log(data); 
      $rootScope.loggedIn = data; 
     }) 
     .error(function(data) { 
      console.log('error: ' + data); 
     }); 
    }; 
}; 

ora è possibile cambiare il valore di loggedIn da altri luoghi nella vostra applicazione accedendo $rootScope.loggedIn nello stesso modo in cui viene fatto nel codice sopra.

Detto ciò, è necessario astrarre il codice pertinente in un servizio e una direttiva. Questo ti consentirebbe di avere un posto centrale per gestire, accedere, disconnettersi e lo stato di $rootScope.loggedIn. Se pubblichi il resto del codice pertinente, potrei aiutarti con una risposta più concreta

+0

rootScope ... Perché non l'ho visto prima? GRAZIE! – Moody

6

È possibile trasmettere quell'evento quando l'utente si collega correttamente. E non c'è bisogno di continuare a interrogare il tuo server se l'utente è loggato puoi tenere una variabile in memoria che ti dice se hai una sessione valida o meno.È possibile utilizzare l'autenticazione basata su token che si trova nel lato server:

services.factory('UserService', ['$resource',           
    function($resource){ 

    // represents guest user - not logged 
    var user = { 
     firstName : 'guest', 
     lastName : 'user', 
     preferredCurrency : "USD", 
     shoppingCart : { 
      totalItems : 0, 
      total : 0 
     },             
    }; 

    var resource = function() { 
     return $resource('/myapp/rest/user/:id', 
      { id: "@id"} 
    )}; 

    return { 
     getResource: function() { 
      return resource; 
     }, 

     getCurrentUser: function() { 
      return user; 
     }, 

     setCurrentUser: function(userObj) { 
      user = userObj; 
     }, 

     loadUser: function(id) { 
      user = resource.get(id); 
     } 
    } 

    }]); 

services.factory('AuthService', ['$resource', '$rootScope', '$http', '$location', 'AuthenticationService', 
    function ($resource, $rootScope, $http, $location, AuthenticationService) { 
    var authFactory = { 
     authData: undefined  
    }; 

    authFactory.getAuthData = function() { 
     return this.authData; 
    }; 

    authFactory.setAuthData = function (authData) { 
     this.authData = { 
      authId: authData.authId, 
      authToken: authData.authToken, 
      authPermission: authData.authPermission 
     }; 
     // broadcast the event to all interested listeners 
     $rootScope.$broadcast('authChanged'); 
    }; 

    authFactory.isAuthenticated = function() { 
     return !angular.isUndefined(this.getAuthData()); 
    }; 

    authFactory.login = function (user, functionObj) { 
     return AuthenticationService.login(user, functionObj);   
    }; 

    return authFactory; 
}]); 

services.factory('AuthenticationService', ['$resource', 
    function($resource){ 
    return $resource('/myapp/rest/auth/', 
      {}, 
      { 
       'login': { method: "POST" } 
      }    
    ); 
    }]);   

services.factory('authHttpRequestInterceptor', ['$injector', 
function ($injector) { 
    var authHttpRequestInterceptor = { 
     request: function ($request) { 
      var authFactory = $injector.get('AuthService'); 
      if (authFactory.isAuthenticated()) { 
       $request.headers['auth-id'] = authFactory.getAuthData().authId; 
       $request.headers['auth-token'] = authFactory.getAuthData().authToken; 
      } 
      return $request; 
     } 
    }; 

    return authHttpRequestInterceptor; 
}]); 

regolatore:

controllers.controller('LoginCtrl', ['$scope', '$rootScope', 'AuthService', 'UserService', 
    function LoginCtrl($scope, $rootScope, AuthService, UserService) { 
    $scope.login = function() { 
     AuthService.login($scope.userInfo, function (data) { 
      AuthService.setAuthData(data); 
      // set user info on user service to reflect on all UI components 
      UserService.setCurrentUser(data.user); 
      $location.path('/home/');    
     }); 
    }; 

    $scope.isLoggedIn = function() { 
     return AuthService.isAuthenticated(); 
    } 

    $scope.user = UserService.getCurrentUser();   
}]) 
0

È possibile aggiungere i dati della sessione dell'utente all'interno del index.html utilizzando alcuni libreria di template come EJS.

Basta aggiungere ejs middleware:

var ejs = require('ejs'); 
 
// Register ejs as .html. 
 
app.engine('.html', ejs.__express);

E poi, al ritorno il index.html rendere i dati di sessione nella risposta.

  res.render("/index.html", { 
 
       session : { 
 
        user_data : JSON.stringify(req.user) 
 
       } 
 

 
      });

Avrai ora possibile accedere a questi dati nel index.html, ora è necessario caricarlo in App angolare. Ho usato l'esempio preload-resource, ma puoi usare la tua strada.

Problemi correlati