简体   繁体   English

使用 ember simple auth 进行身份验证后加载用户

[英]User loading after authentication with ember simple auth

I use ember simple auth to authenticate my users.我使用 ember simple auth 来验证我的用户。 It workls perfectly fine except when the user just logged in.它工作得非常好,除非用户刚刚登录。

I have an helper that ask for the current user:我有一个助手询问当前用户:

import Helper from '@ember/component/helper';
import { inject as service } from '@ember/service';

export default Helper.extend({
  currentUser: service('current-user'),
  compute([feature,currentUser]) {
    let role = currentUser.get('user.role')

Helper is used in a template embedded in a template in application.hbs Helper 用于嵌入在 application.hbs 中的模板中的模板

{{#if (permission-for "users" currentUser)}}
  <li>{{#link-to 'users'}}<i class="fa fa-user"></i> <span>Clients</span>{{/link-to}}</li>
  {{/if}}

The current user service is a duplicate of this one from the doc: https://github.com/simplabs/ember-simple-auth/blob/master/guides/managing-current-user.md#loading-the-user-with-its-id当前的用户服务与文档中的这个重复: https://github.com/simplabs/ember-simple-auth/blob/master/guides/managing-current-user.md#loading-the-user-带有它的 ID

And my application.js is also using the code from the same guide.我的 application.js 也在使用同一指南中的代码。

From what I tried, the sessionAuthenticated start to run, and during await this._loadCurrentUser();根据我的尝试, sessionAuthenticated开始运行,并且在await this._loadCurrentUser(); the helper is executed, and it finish to run sessionAuthenticated助手被执行,并完成运行sessionAuthenticated

What happen is that the user attribute I want is undefined and it make it impossible to display interface elements according to the role of the User.发生的情况是我想要的用户属性未定义,并且无法根据用户的角色显示界面元素。

How can I fix this problem?我该如何解决这个问题?

Edit for related question:How does ember simple auth is supposed to be used in template to determine if User is supposed to see some part of the interface or not?编辑相关问题:如何在模板中使用 ember simple auth 来确定用户是否应该看到界面的某些部分? Like for example menu choices.例如菜单选择。

First I would recommend to not pass the currentUser service to the helper if you inject it to the service.首先,如果您将currentUser服务注入服务,我建议不要将其传递给帮助程序。

Next you can let the helper recompute after the user was loaded:接下来,您可以在加载用户后让帮助程序重新计算:

export default Helper.extend({
  currentUser: service('current-user'),
  init() {
    if(!this.currentUser.user) {
      this.currentUser.runAfterLoaded.push(() => this.recompute());
    }
  },
  compute([feature]) {
    if(!this.currentUser.user)
      return false;
    }
    let role = this.currentUser.get('user.role')
    ...
    return ..;
  }
});

you'll also want to add this.runAfterLoaded.forEach(x => x()) to the load() function in the current-user service after the this.set('user', user);您还需要在this.set('user', user);之后将this.runAfterLoaded.forEach(x => x())添加到current-user服务的load() function; as well as this.set('runAfterLoaded', []) to the init hook.以及this.set('runAfterLoaded', [])init钩子。


Another possibility is to build a mixin that you add to the relevant routes after the AuthenticatedRouteMixin that ensures the current user will be loaded.另一种可能性是构建一个 mixin,在AuthenticatedRouteMixin之后添加到相关路由,以确保加载当前用户。

The problem with your approach is the helper is being executed synchronously and isn't "watching" the currentUser service in a way that would recompute.您的方法的问题是助手正在同步执行,并且没有以重新计算的方式“监视” currentUser服务。 It would be a lot easier to use a computed property to do what you want:使用计算属性来做你想做的事情会容易得多:

controllers/application.js控制器/application.js

  currentUser: service(),

  hasPermissionForUsers: computed("currentUser.user", function() {
    const user = this.get("currentUser.user");

    if (! user) return false;

    return user.get("role") === "users"; // taking a random guess at what your helper does here
  })

This property will now re-compute once the user is loaded:加载用户后,此属性现在将重新计算:

application.hbs应用程序.hbs

  {{#if hasPermissionForUsers}}
    <li>{{#link-to 'users'}}<i class="fa fa-user"></i> <span>Clients</span>{{/link-to}}</li>
  {{/if}}

If you have to use a helper, it is doable but it's not pretty.如果你必须使用助手,它是可行的,但它并不漂亮。 The reason it's not as elegant is because helpers don't have access to the same context so it's more difficult to recompute.它不那么优雅的原因是助手无法访问相同的上下文,因此重新计算更加困难。 You could do something like this:你可以这样做:

import Helper from '@ember/component/helper';
import { inject as service } from '@ember/service';
import { run } from '@ember/runloop';
import { addObserver, removeObserver } from '@ember/object/observers';

export default Helper.extend({

  currentUser: service(),

  willDestroy() {
    this._super(...arguments);
    const container = this.get('_container');
    removeObserver(container, 'currentUser.user', this, this.update);
  },

  compute([feature, container]) {
    addObserver(container, 'currentUser.user', this, this.update);
    this.set('_container', container); // used for cleanup

    const user = this.get('currentUser.user');

    if (! user) return false;

    return user.get('role') === feature;
  },

  update() {
    run.once(this, this.recompute);
  }
});

Then use it like so:然后像这样使用它:

application.hbs应用程序.hbs

{{#if (permission-for "users" this)}}
  <li>{{#link-to 'users'}}<i class="fa fa-user"></i> <span>Clients</span>{{/link-to}}</li>
{{/if}}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM