登录后同步注入当前用户
在我的EmberJS应用程序中,我有一个当前用户初始化程序,它将用户注入所有控制器,路由和视图。它在登录时效果很好。我需要同步加载当前用户对象,以便我可以立即检查一些用户权限。登录后同步注入当前用户
这里是我的初始化:
App.CurrentUserInitializer - Ember.Initializer.extent({
name: 'current-user',
after: 'authentication',
initialize: function(container, app) {
var store = container.lookup('store:main');
app.deferReadiness();
store.find('user', 'me').then(function (user) {
app.register('session:user', user, {instantiate: false});
_.forEach(['route', 'controller', 'view'], function (place) {
app.inject(place, 'currentUser', 'session:user');
});
app.advanceReadiness();
}).catch(function() {
app.advanceReadiness();
});
}
});
如果这打破了我,是在登录过程中。当应用程序启动时,初始化程序运行,但/users/me
路径返回401错误。如果我没有发现错误和advanceReadiness,请启动暂停。通过捕获错误,应用程序启动,但初始化程序在登录后不会再次运行,因此当前用户未加载。
我在这里有什么选择?我无法使用@ marcoow推荐的将计算属性添加到Session的方法,因为我需要在启动时加载用户。
我试过强制加载用户对象的IndexRoute作为黑客,但似乎并没有工作。
任何提示将不胜感激。
我会注册一个session:current
对象与user
属性为空。这将被注入到controllers
和routes
(不确定注入内部视图是一个好主意)。
所以在开机时user
是未知的,但是路由器出现深度超过application
路线,根之前,用户查找完成:
在beforeModel
钩application
路线,你会加载电流用户。然后:
- 要么你得到了用户并设置其
this.set('session.user', model)
- ,否则你会在
error
钩application
路线,在这种情况下,你必须检查为什么要去,如果401
然后您可以将用户重定向到登录路由this.transitionTo('login')
不要忘记设置标志上session
如果你得到了401
使transitionTo
将使我们的用户beforeModel
查找,直到我们再发生到达login
路线
该代码被用来加载会话用户和初始化它可以被放置在该session:current
对象,以便能够从application
路线或login
控制器调用它。
这是例如我的session
初始化(不完全如我所解释的,但在初始化程序中加载,因此更接近你的)。我使用了一个session
模型,因此我做了/session/current
,然后让一个用户进入(或不是)有正确的ID而不是me
然后这会让商店加载同一用户与另一个ID,所以有两次相同用户为2个不同的记录:
app/models/session。JS:
import DS from 'ember-data';
import Ember from 'ember';
export default DS.Model.extend({
user: DS.belongsTo('user'),
isAuthenticated: Ember.computed.bool('user.isClaimed')
});
应用程序/初始化/ session.js:
import Ember from 'ember';
export default {
name: 'session',
after: 'store',
initialize: function (container, app) {
var store = container.lookup('store:main'),
sid = Ember.$.cookie('sid');
// used to register a session
var register = function (session) {
app.register('session:main', session, {instantiate: false});
app.inject('route', 'session', 'session:main');
app.inject('controller', 'session', 'session:main');
};
// used to create a new session and trigger the backend to get details about it
// useful if the server is able to give an existing session while the browser doesn't know about it
// with external providers for example
var newSession = function() {
var session = store.createRecord('session');
// be sure to wipe out any invalid session ID
Ember.$.removeCookie('sid');
register(session);
return session.save().then(function (model) {
// if we got a valid new session, save its ID
Ember.$.cookie('sid', model.get('id'));
}).catch(function() {
Ember.debug('error saving new session: ' + Array.prototype.join.call(arguments, ', '));
});
};
// overall logic ==================
app.deferReadiness();
if (sid) {
// try to load the existing session
store.find('session', sid).then(function (model) {
register(model);
app.advanceReadiness();
}).catch(function() {
// there was a cookie for the session but it might have expired or the server invalidated it
Ember.debug('error loading session: ' + Array.prototype.join.call(arguments, ', '));
newSession().finally(function() {
app.advanceReadiness();
});
});
}
else {
// we don't have any trace of a session, let's just create a new one
newSession().finally(function() {
app.advanceReadiness();
});
}
}
};
应用程序/ router.js:
import Ember from 'ember';
var Router = Ember.Router.extend();
Router.map(function() {
this.resource('session', {path: '/'}, function(){
this.route('login');
this.route('logout');
});
});
export default Router;
应用/模板/ application.hbs(举例):
<h2 id='title'>Welcome to my app</h2>
{{#if session.isAuthenticated}}
<a {{action 'session.logout'}}>Logout</a>
{{else}}
{{#link-to 'session.login'}}Login{{/link-to}}
{{/if}}
{{outlet}}
然后一旦在登录控制器中,当用户实际登录时,服务器将返回session
模型,用户链接到该模型,因此Ember绑定魔术只会更新会话对象。
@华孚你有代码示例可以显示吗?仅供参考 - 我使用的是ember-simple-auth,每当我在应用程序路径上使用beforeModel时,即使返回履行的承诺,启动也会停止。 – ToddSmithSalter 2014-09-23 17:43:15
啊,如果你正在使用'ember-simple-auth',那么你应该在你的问题中说出它,因为我不确定它是如何工作的,但肯定会使我的答案的某些部分失效。 我会添加一个示例,但它只是没有简单验证。我听说过简单的身份验证,但没有使用它,所以不能举一个例子。是的,在'beforeModel'挂钩中放置承诺的目标是暂停路由器,也许这是简单的认证,以某种方式暂停启动,但通常一旦承诺完成,它应该继续启动 – Huafu 2014-09-24 00:03:44
@ToddSmithSalter,刚刚更新东西使用初始化;-) – Huafu 2014-09-24 01:43:03