Подтвердить что ты не робот

Как сохранить глобальный текущий пользователь до выхода из системы с помощью angular_devise?

Как создать собственную услугу, доступную по всему миру, которая будет вызывать сервер currentUser() только один раз при загрузке страницы, если пользователь зарегистрирован, а затем сохранит его и предоставит данные контроллерам или состояниям до выхода из системы? Теперь я решаю много раз во многих состояниях или контроллерах currentUser(), я нашел в документах: authparseresponse, что это возможность сделать собственный сервис, но я не знаю, как правильно это сделать.

например, в ui-router У меня два вызова сервера, будет достаточно только при загрузке страницы:

.state('login', {
  url: '/login',
  templateUrl: 'auth/_login.html',
  controller: 'AuthCtrl',
  onEnter: [
    '$state', 'Auth',
    function($state, Auth) {
      Auth.currentUser().then(function() {
        $state.go('home');
      });
    }
  ]
})
.state('dashboard', {
  url: '/dashboard',
  templateUrl: 'dashboard.html',
  onEnter: [
    '$state', 'Auth',
    function($state, Auth) {
      Auth.currentUser().then(function(user) {}, function(err) {
        $state.go('home');// user not logged in
      });
    }
  ]
})

или каждый раз при следующем вызове сервера в NavController:

app.controller('NavController', [
  '$state', '$scope', 'Auth', function($state, $scope, Auth) {
    $scope.signedIn = Auth.isAuthenticated;
    $scope.logout = Auth.logout; // logout function
    Auth.currentUser().then(function(user) {
      $scope.user = user;
    });
    $scope.$on('devise:login', function(e, user) {
      $scope.user = user;
    });
    $scope.$on('devise:logout', function(e, user) {
      $scope.user = {};
      $state.go("home");
    });
  }
]);

Я нашел подобный вопрос без ответа: qaru.site/info/278184/...

4b9b3361

Ответ 1

Как известно, factory является одноэлементным объектом и в основном используется для совместного использования данных. Мы можем вводить его любому контроллеру и работать как зависимость . Это также может решить вашу проблему. вставьте эту службу в свой блок разрешения состояния и проверьте, существует ли пользователь или нет, если нет, то вызовите функцию пользователя fetch из factory

app.factory("User", function($http, $q, $rootScope) {
var user = null;
return {
    fetchUser: function() {
        /*your ajax call that return current user*/
        user = YOUR_SERVER_RESPONSE;
        return user;

    },
    getUser : function(){
        return user;
    },
    setUser : function(u){
        user = u;
    }
}

});

и ваш блок конфигурации состояния выглядит как

  .state('dashboard', {
  url: '/dashboard',
  templateUrl: 'dashboard.html',
  resolve : function(User){
    if(User.getUser()){
        return User.getUser();
    }else{
        return User.fetchUser();
    }
  }
})

Ответ 2

Мне пришлось иметь дело с аутентификацией пользователя в большом приложении Angular и нашел эту статью очень полезной: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec p >

Конкретно, как это сделать только один раз:

  • вы можете вызвать init() службы в блоке app.run
  • добавление его в качестве требования resolve внешнего состояния для приложения (если вы используете вложенные состояния)

A UserService Служба для представления пользователя, зарегистрированного в состоянии, хорошо работает для совместного использования состояния во всем приложении. Через эту службу можно открыть функции входа и выхода из системы, и здесь также могут быть сохранены данные пользователя. Определение UserApi, которое расширяет $resource, вероятно, поможет также отделить фактические проблемы HTTP от управления состоянием пользователя.

Другие проблемы, которые вас поймают, оба из которых описаны в статье: постоянное состояние обновлений на странице и наличие областей сайта, которые доступны только при входе пользователя.

Ответ 3

Я решил проблему с информацией current_user с помощью angular, добавив следующий код JavaScript (jQuery) в конец моей основной HTML-страницы:

$("meta[name=current_user]").data('current_user', {
    id: <%=j current_user.id.to_s %>, 
    username: "<%=j current_user.full_name.to_s %>"
});

Вы можете анализировать любую информацию, которая вам нужна, это может быть Rails Project и все, что мне нужно, это ID и NAME (с идентификатором я может запрашивать объект User factory и получать JSON с полной информацией если понадобится).

Затем в вашем контроллере AngularJS вы можете добавить (мой кофейник):

# Grab User Info
current_user = angular.element("meta[name=current_user]").data 'current_user'

# Stop Here if you Have the Info you Need
$scope.user = current_user

# **** OR Get More Info if User is Logged In 
if current_user.id is not undefined
   $scope.user = User.get {id: current_user.id}

Вот мой Factory Код для пользователя (coffeescript снова):

# In order to prevent minification from effecting the code
# must wrap functions as arrays and pass in the variables as 
# strings before the function call
app.factory "User", ["$resource", ($resource) ->
    $resource("/api/angular/users/:id", 
    { id: "@id" }, 
    {
        update: { method: "PUT" }
    })
]

Сообщите мне, если у вас есть какие-либо вопросы.

Ответ 4

Изменить: изменение некоторых частей для использования с модулем angular_device

Как правило, я использую предоставленное здесь решение (https://vickev.com/#!/article/authentication-in-single-page-applications-node-js-passportjs-angularjs), в котором описывается, как проверить, зарегистрирован ли пользователь для каждого HTTP-вызов.

Проверка загрузки, если пользователь зарегистрирован

myApp.config(['$routeProvider','$locationProvider',
function($routeProvider, $locationProvider) {
//================================================
// Check if the user is connected
//================================================
var checkLoggedin = function($q, $rootScope, Auth, User){
  // Initialize a new promise
  var deferred = $q.defer();
  Auth.currentUser().then(function(userObj){
    deferred.resolve();
    //option a: just save the user object into the $rootScope
    $rootScope.User = userObj;
    //option b: create a factory 'User' and a method 'save()' which parses the JSON returned from your Server 
    User.save(userObj);
  }, function(error){
    deferred.reject();
  });
  return deferred.promise;
};


//================================================
// Define all the routes
//================================================
$routeProvider
  //Start page, where the user gets a list of registered SO and can add new ones
  .when('/', {
    templateUrl: 'templates/index.html', 
    controller: 'indexCtrl',
    resolve: {
      loggedin: checkLoggedin
    }
  })
  .when('/login', {
    templateUrl: 'templates/login.html', 
    controller: 'loginCtrl'
  })
  // do more here
  .otherwise({
      redirectTo: '/'
  });
}]).run(function($rootScope, $http){
//Do some initial tasks or set some values
});

Я бы создал дополнительную службу с именем "Пользователь" (поскольку сервисы являются одноточечными), определите некоторые методы, например. save() и get(), чтобы сохранить пользователя в сервисе singleton и получить его, когда это необходимо. С помощью функции "checkLoggedIn" вы можете определить параметр "разрешение" для своих маршрутов, и если обещание будет разрешено, пользователь сможет получить доступ к странице с ограничениями.

Ответ 5

Сохраните данные пользователя в Global.user, используя модуль "Глобальный" в контроллерах или службах.

когда вам нужно получить доступ к пользователю, затем используйте Global.user