casl: Overriding via provide in a plugin causes strange behavior in templates

Describe the bug If you provide an ability through a plugin defined after the vue plugin is setup you will get undetermined behavior including the following error every time you try to use can on it’s own in a template:

index.mjs:1 Uncaught (in promise) TypeError: "this.relevantRuleFor" is not a function

To Reproduce Steps to reproduce the behavior:

  1. Define any ability function
  2. create a plugin to inject abilities based on application changes after the vue plugin is installed such as
install(app, config){
 watch(thing, () => {
   app.provide(ABILITY_TOKEN, defineAbility(thing.value)
 })
}
  1. How do you check abilities

const { can } = useAbility()

When you use can in the template you’ll get the above error for any check. But, if you do the same check by doing

const ability = useAbility()

in the script setup for the component it will be valid e.g ability.can('do', 'Thing')

but you can’t pass or proxy can into the template without explicitly taking all the parameters from the template.

if you do do this, it seems the ability is fine. e.g.

<template>
<div v-if="can('view', 'Thing')> hi </div>
</template>
<script setup>
const ability = useAbility()
const can = (perm, thing) => { return ability.can(perm, thing) }
</script>

Expected behavior The page doesnt error

CASL Version

@casl/ability - 6.5.0 @casl/vue - 2.2.1

Environment:

Chrome, latest Typescript, 4.9.5

About this issue

  • Original URL
  • State: closed
  • Created 10 months ago
  • Reactions: 1
  • Comments: 19 (9 by maintainers)

Most upvoted comments

You can use any ability instance. It can also be PureAbility. This is just what my fingers now to type ))

let me know if you will have further questions