登录后同步注入当前用户

时间:2014-09-23 00:16:39

标签: ember.js initializer ember-simple-auth

在我的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上的用户对象加载为hack,但这似乎不起作用。

任何提示都表示赞赏。

1 个答案:

答案 0 :(得分:5)

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

因此,在启动时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的相同用户,因此具有两个相同的用户和两个不同的记录:

应用/模型/ 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;

app / templates / 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绑定魔法将只更新会话对象。