Как сохранить глобальный текущий пользователь до выхода из системы с помощью 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/...
Ответы
Ответ 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