Загрузка пользователя после аутентификации с помощью ember simple auth - PullRequest
1 голос
/ 23 октября 2019

Я использую ember simple auth для аутентификации моих пользователей. Он отлично работает, за исключением случаев, когда пользователь только что вошел в систему.

У меня есть помощник, который запрашивает текущего пользователя:

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')

Помощник используется в шаблоне, встроенном в шаблон в приложении.hbs

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

Текущий пользовательский сервис является дубликатом этого документа из документа: https://github.com/simplabs/ember-simple-auth/blob/master/guides/managing-current-user.md#loading-the-user-with-its-id

И мой application.js также использует код из того же руководства.

Из того, что я пытался, sessionAuthenticated начинает работать, и во время await this._loadCurrentUser(); выполняется помощник, и он завершает работу sessionAuthenticated

Что происходит, когда пользовательский атрибут Iхотение не определено, и это делает невозможным отображение элементов интерфейса в соответствии с ролью пользователя.

Как я могу решить эту проблему?

Редактировать для связанного вопроса: Как работает простой тлеющий аутентификатордолжен использоваться в шаблоне, чтобы определить, должен ли пользователь видеть какую-то часть интерфейса или нет? Как например выбор меню.

Ответы [ 2 ]

2 голосов
/ 23 октября 2019

Проблема с вашим подходом заключается в том, что помощник выполняется синхронно и не "наблюдает" за сервисом currentUser таким образом, который бы пересчитывал. Было бы намного проще использовать вычисляемое свойство, чтобы делать то, что вы хотите:

controllers / 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
  })

Это свойство теперь будет пересчитанокак только пользователь загружен:

application.hbs

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

Если вам нужно использовать помощника, это выполнимо, но это не красиво. Причина, по которой он не такой элегантный, заключается в том, что у помощников нет доступа к одному и тому же контексту, поэтому пересчитать сложнееВы можете сделать что-то вроде этого:

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);
  }
});

Затем использовать это так:

application.hbs

{{#if (permission-for "users" this)}}
  <li>{{#link-to 'users'}}<i class="fa fa-user"></i> <span>Clients</span>{{/link-to}}</li>
{{/if}}
1 голос
/ 23 октября 2019

Сначала я бы порекомендовал не передавать службу currentUser помощнику, если вы внедрили ее в службу.

Затем вы можете разрешить помощнику пересчитываться после загрузки пользователя:

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 ..;
  }
});

вы также захотите добавить this.runAfterLoaded.forEach(x => x()) к функции load() в сервисе current-user после this.set('user', user);, а также this.set('runAfterLoaded', []) к init hook.


Другой возможностью является создание миксина, который вы добавляете в соответствующие маршруты после AuthenticatedRouteMixin, который гарантирует загрузку текущего пользователя.

...