1
\$\begingroup\$

I have an endpoint to retrieve the user's authorization based on Joseph Silber's Bouncer.

I have a global can() function. It creates a unique key based on the authorization request and sets an object's property based on that key.

can (ability, model = null, id = null) {
  const key = `${ability}_${model}_${id}`
  const params = {
    ability, model, id
  }

  axios.get(this.route('authorize', params))
    .then(res => {
      Vue.set(this.userAuthorizations, key, res.data.allowed)
    })
    .catch(err => this.showError(err.message))

  return key
}
data () {
  return {
    userAuthorizations: {}
  }
}

So in a template, I do something like...

<button v-if="userAuthorizations[can('create', 'users')]">
  Create User
</button>

There will be a delay while it's retrieving the result, but since the key doesn't exist it won't show a restricted thing.

It looks ugly to me, but it's the most sustainable and reusable way I could think to do it on the front-end. Thoughts? What's a better way?

\$\endgroup\$
  • 2
    \$\begingroup\$ Welcome to Code Review where we review the code and provide suggestions on how to improve that code. Questions that include hypothetical code such as ` Restricted thing .Please see our guidelines on asking. \$\endgroup\$ – pacmaninbw Jul 14 at 15:43
  • 1
    \$\begingroup\$ @pacmaninbw I've changed the language to reflect real code. \$\endgroup\$ – Grant Jul 14 at 23:56
0
\$\begingroup\$

Bearing in mind that it is a feature, instead of waiting for the promise to be fulfilled with a callback:

axios.get(this.route('authorize', params))
   .then(res => {
     Vue.set(this.userAuthorizations, key, res.data.allowed)
   })
   .catch(err => this.showError(err.message))

the code could wait until the response is retrieved using await:

async can (ability, model = null, id = null) {
  const key = `${ability}_${model}_${id}`
  const params = {
    ability, model, id
  }

  const response = await axios.get(this.route('authorize', params))
    .catch(err => this.showError(err.message))

  Vue.set(this.userAuthorizations, key, res.data.allowed)
  return res.data.allowed
}  

Note that can() needs to be declared as async in order for await to be permitted inside of it.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ I think if I remember correctly, I did use async/await but it didn't play nice as a v-if. I could be misremembering. Doing this would also change the conditional right? So v-if="can('create', 'users') \$\endgroup\$ – Grant Sep 3 at 13:07
  • \$\begingroup\$ That probably would be an issue... is there a way to fetch the data in a lifecycle hook like created(), mounted(), etc. or would there be an indeterminate amount of parameters? \$\endgroup\$ – Sᴀᴍ Onᴇᴌᴀ Sep 3 at 15:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.