登录后同步注入当前用户

Tod*_*ter 2 initializer ember.js 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();
      });
    }
});
Run Code Online (Sandbox Code Playgroud)

这对我来说是崩溃的,是在登录期间.应用程序启动时,将运行初始化程序,但/users/me路径返回401错误.如果我没有捕获错误和advanceReadiness,则启动暂停.通过捕获错误,应用程序启动,但登录后初始化程序不会再次运行,因此不会加载当前用户.

我有什么选择?我不能使用@ marcoow推荐的向Session添加计算属性的方法,因为我需要在启动时加载用户.

我已经尝试强制将IndexRoute上的用户对象加载为hack,但这似乎不起作用.

任何提示都表示赞赏.

Hua*_*afu 5

我注册了一个属性为null 的session:current对象user.这将注入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的相同用户,因此具有两倍于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')
});
Run Code Online (Sandbox Code Playgroud)

app/initializers/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();
      });
    }
  }
};
Run Code Online (Sandbox Code Playgroud)

app/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;
Run Code Online (Sandbox Code Playgroud)

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}}
Run Code Online (Sandbox Code Playgroud)

然后在登录控制器中,当用户实际登录时,服务器将返回session模型,并将用户链接到该模型,因此Ember绑定魔法将只更新会话对象.