2

也许我忽略了一些非常容易的事情,但是我已经看了两天了,我无法弄清楚。

我有一个 Vue 应用程序,我想根据他的角色指定用户可以看到什么或他可以去哪里。我为此使用 casl-vue。

我想在两个时刻设置该功能,加载页面时和登录后。

页面加载时

当我使用同步函数注册功能时,一切正常,如下所示:

main.js

import { abilitiesPlugin } from '@casl/vue';
import ability from '../config/ability';
Vue.use(abilitiesPlugin, ability);

能力.js

import { AbilityBuilder, Ability } from '@casl/ability';

export default AbilityBuilder.define((can, cannot) => {
  const role = 'Admin';

  switch (role) {
    case 'Admin':
      can('manage', 'all');
      break;
    case 'Author':
      can('manage', 'all');
      cannot('manage', 'users');
      break;
    case 'Trainer':
      break;
    case 'Participant':
      cannot('manage', 'all');
      break;
    default:
      cannot('manage', 'all');
  };
})

但是,当我想使用返回承诺 (getCurrentUserRole()) 的函数获取角色时,因此使函数异步如下:

能力.js

export default AbilityBuilder.define(async (can, cannot) => {
  const role = await getCurrentUserRole();

  switch (role) {
    case 'Admin':
      can('manage', 'all');
      break;
    ...
    default:
      cannot('manage', 'all');
  };
})

我收到以下错误:

“TypeError:ability.on 不是函数”

登录后

值得庆幸的是,登录后更新能力规则可以使用 this.$ability.update:

const { role } = await someSignInFunction();
this.$ability.update(defineRulesFor(role));
this.$router.push({ name: 'home' });

但是,我似乎无法在页面加载时使用此功能,因为当我将其放入 App.vue 中时(例如,在beforeCreate()or中created()),在我调用ability.update 之前页面已经加载,因此更新能力“为时已晚” .

Vue路由器

我还想访问我的 Vue 路由器实例中的能力可以方法(以控制我的用户可以访问的路由),但是我如何访问我的路由器文件中的能力实例?

如果在任何情况下我的问题没有得到很好的解释,请告诉我!

如果有人可以帮助我设置设置结构,我将不胜感激。

依赖项:

casl/ability: ^3.3.0
casl/vue: ^0.5.1
4

1 回答 1

3

问题是,如果您async在内部传递函数,AbilityBuilder.defineAbilityBuilder.define返回一个Promise. 它不能神奇地使异步代码同步:)

因此,您需要做的是创建一个单独的函数defineRulesFor(role)

// src/config/rules.js

import { AbilityBuilder } from '@casl/ability'

export default function defineRulesFor(role) {
  const { can } = AbilityBuilder.extract()

  switch (role) {
    case 'Admin':
      can('manage', 'all');
      break;
    case 'Author':
      can('manage', 'all');
      cannot('manage', 'users');
      break;
    case 'Trainer':
      break;
    case 'Participant':
      cannot('manage', 'all');
      break;
    default:
      cannot('manage', 'all');
  }
} 

然后登录后:

// inside Login.vue
import defineRulesFor from '../config/rules'

export default {
  name: 'LoginPage',
  methods: {
    async login() {
      const response = await axios.post(...)
      const user = response.data
      this.$ability.update(defineRulesFor(user.role))
    }
  }
}

现在你有两个选择:

  1. 将用户角色存储在本地存储中并在页面重新加载时恢复:
// inside App.vue

import defineRulesFor from './config/rules'

export default {
  name: 'App',
  created() {
    this.$ability.update(defineRulesFor(localStorage.getItem('userRole'))
  }
}
  1. 在页面重新加载时重新获取有关用户的信息
// inside App.vue

import defineRulesFor from './config/rules'

export default {
  name: 'App',
  async created() {
    const role = await getCurrentUserRole()
    this.$ability.update(defineRulesFor(role))
  }
}
于 2019-12-17T19:38:14.563 回答