AngularJS-afficher / masquer les éléments nav si l'utilisateur est connecté

J'ai une application AngularJS d'une page, travaillant avec Express, node.JS, et MongoDB via Mongoose. Utilisation du passeport pour la gestion et l'authentification des utilisateurs.

j'aimerais que les éléments de la barre de navigation changent selon qu'un utilisateur est connecté ou non. Je vais avoir de la difficulté à trouver comment la mettre en œuvre.

je découvre si un utilisateur est connecté via un http demande:

le serveur.js

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

Sur le front-end, j'ai un NavController appel à L'aide D'Angular$http service:

NavController.js

angular.module('NavCtrl',[]).controller('NavController',function($scope,$http) {

    $scope.loggedIn = false;

    $scope.isLoggedIn = function() {

      $http.get('/checklogin')
        .success(function(data) {
          console.log(data);
          if (data === true)
            $scope.loggedIn = true;
          else
            $scope.loggedIn = false;
        })
        .error(function(data) {
          console.log('error: ' + data);
        });
    };
};

Dans mon nav, je suis en utilisant ng-show et ng-hide pour déterminer les sélections doivent être visibles. Je suis également le déclenchement de l' isLoggedIn() fonction lorsque l'utilisateur clique sur les éléments de nav, vérifier si l'utilisateur est connecté pendant chaque 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>

Problème

il y a d'autres endroits dans mon application où l'utilisateur peut se connecter/Se Déconnecter, en dehors du champ D'application du NavController. Par exemple, il y a un bouton de connexion sur la page de connexion, qui correspond au LoginController. J'imagine qu'il y a une meilleure façon d'implémenter ceci dans toute mon application.

Comment puis-je surveiller si req.usertrue sur l'arrière et est-ce que mes articles nav répondent en conséquence?

17
demandé sur Ryan Tuck 2014-11-14 02:12:05

4 réponses

vous pouvez utiliser $rootScope pour partager des informations à travers l'ensemble de l'application:

.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);
        });
    };
};

maintenant vous pouvez changer la valeur de loggedIn à partir d'autres endroits dans votre application en accédant $rootScope.loggedIn de la même manière que dans le code ci-dessus.

cela dit, vous devez abstraire le code pertinent en un service et une directive. Cela vous permettrait d'avoir une place centrale à manipuler, connexion, déconnexion, et l'état d' $rootScope.loggedIn. Si vous publiez le reste du code je pourrais vous aider avec plus concret en réponse

11
répondu Nicolás Straub 2015-06-30 02:42:21

Vous pouvez diffuser cet événement lorsque l'utilisateur se connecte avec succès. Si l'utilisateur est connecté, vous pouvez garder une variable en mémoire qui indique si vous avez une session valide ou non. Vous pouvez utiliser une authentification basée sur un token qui est définie du côté du serveur:

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;
}]);

contrôleur:

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();         
}])
6
répondu guilhebl 2014-11-13 23:58:53

vous pouvez ajouter les données de session de l'utilisateur dans l'index.html utilisant une bibliothèque de Templiers comme EJS.

Juste ajouter ejs middleware:

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

et puis, en retournant l'index.html affiche les données de la session dans la réponse.

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

            });

Vous aurez maintenant accès à ces données dans l'index.html, maintenant vous devez le charger dans l'application angulaire. J'ai utilisé précontrainte-ressource exemple, mais vous pouvez utiliser votre propre chemin.

0
répondu yotamsha 2014-11-14 00:03:35

vous pouvez aussi utiliser $localStorage si vous voulez que le login persiste en dehors de la session en cours. J'ai trouvé que cette bibliothèque a été super utile pour ce genre de situations. (https://github.com/grevory/angular-local-storage)

0
répondu Jonathan 2015-06-30 03:10:55