2014-09-23 60 views
2

在我的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作为黑客,但似乎并没有工作。

任何提示将不胜感激。

回答

5

我会注册一个session:current对象与user属性为空。这将被注入到controllersroutes(不确定注入内部视图是一个好主意)。

所以在开机时user是未知的,但是路由器出现深度超过application路线,根之前,用户查找完成:

beforeModelapplication路线,你会加载电流用户。然后:

  • 要么你得到了用户并设置其this.set('session.user', model)
  • ,否则你会在errorapplication路线,在这种情况下,你必须检查为什么要去,如果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绑定魔术只会更新会话对象。

+0

@华孚你有代码示例可以显示吗?仅供参考 - 我使用的是ember-simple-auth,每当我在应用程序路径上使用beforeModel时,即使返回履行的承诺,启动也会停止。 – ToddSmithSalter 2014-09-23 17:43:15

+0

啊,如果你正在使用'ember-simple-auth',那么你应该在你的问题中说出它,因为我不确定它是如何工作的,但肯定会使我的答案的某些部分失效。 我会添加一个示例,但它只是没有简单验证。我听说过简单的身份验证,但没有使用它,所以不能举一个例子。是的,在'beforeModel'挂钩中放置承诺的目标是暂停路由器,也许这是简单的认证,以某种方式暂停启动,但通常一旦承诺完成,它应该继续启动 – Huafu 2014-09-24 00:03:44

+0

@ToddSmithSalter,刚刚更新东西使用初始化;-) – Huafu 2014-09-24 01:43:03