Iview – Admin2.0 built-in permission management

Iview-admin2.0 has its own permission management. You can assign permission by setting the parameter access of the meta object of the route. The default roles are super_admin and admin, and now we assign the document sidebar item a permission that only user can view

{path: "', name: 'doc' meta: {title: 'document' href: 'https://lison16.github.io/iview-admin-doc/#/' icon: 'ios-book', access: ['user'] } },Copy the code

The sidebar will not show the document column. Get menuList in SRC /store/module/app.js, which is the list in the sidebar

  getters: {
    menuList: (state, getters, rootState) => getMenuByRouter(routers, rootState.user.access),
    errorCount: state => state.errorList.length
  },
Copy the code

The getter method basically executes getMenuByRouter and then looks at SRC /libs/util.js to find the code

/** * @return {Array} */ export const getMenuByRouter = (list, access) => { let res = [] forEach(list, item => { if (! item.meta || (item.meta && ! item.meta.hideInMenu)) { let obj = { icon: (item.meta && item.meta.icon) || '', name: item.name, meta: item.meta } if ((hasChild(item) || (item.meta && item.meta.showAlways)) && showThisMenuEle(item, access)) { obj.children = getMenuByRouter(item.children, access) } if (item.meta && item.meta.href) obj.href = item.meta.href if (showThisMenuEle(item, access)) res.push(obj) } }) return res }Copy the code
const showThisMenuEle = (item, access) => {
  if (item.meta && item.meta.access && item.meta.access.length) {
    if (hasOneOf(item.meta.access, access)) return true
    else return false
  } else return true
}
Copy the code

Here, the process of access judging permissions is more clear. [‘admin’,’super_admin’]; [‘admin’,’super_admin’]; [‘admin’,’super_admin’]; [‘admin’,’super_admin’] But we set access to the document to [‘user’],

HasOneOf ([' admin ', 'super_admin], [' user']) / / false, authentication failedCopy the code

HasOneOf is a utility method for iView-admin. To determine whether the array to be queried contains at least one element in the target array, the detailed code is placed at the bottom.

Display by permission control component

Generally we also need to control the presentation of page elements, such as buttons, based on permissions. There are two methods: one is to customize the Auth directive, or to customize an authentication component to wrap around the element that requires authentication.

Custom auth directive

Iview-admin stores the custom directives in the SRC /directive folder. The cache. js file is responsible for importing the custom directives defined separately in each file and exporting them collectively. We implement an auth directive:

import draggable from './module/draggable'
import clipboard from './module/clipboard'
import auth from './module/auth'
const directives = {
  draggable,
  clipboard,
  auth
}
export default directives
Copy the code

We then export an importDirective method in SRC /directive/index.js with Vue as the input and the logic as the register directive.

Import directive from './directives' const importDirective = Vue => {/** * Drag the v-draggable="options" * options = {* Trigger: / pass in the CSS selector as the drag trigger /, * body: / pass in the CSS selector that needs to move the container /, * recover: / *} */ vue. directive('draggable', Directive. Draggable) /** * clipboard v-draggable="options" * options = {* value: / / use the v-model binding value in the input box /, * success: /, * error: Directive ('clipboard', directive.clipboard) vue. directive('auth', directive.auth) } export default importDirectiveCopy the code

The importDirective method is used in main.js and takes the actual Vue as an input parameter.

Import importDirective from '@/directive' /** * register directive */ importDirective(Vue)...Copy the code

Edit the SRC/directive/module/auth. Js

import store from '@/store'
export default {
  inserted: (el, binding, vnode) => {
    const value = binding.value
    const access = store.state.user.access
    if (access.indexOf(value) === -1) {
      el.remove()
    }
  }
}
Copy the code

Let’s add an auth directive and export it. Make a permission judgment at injection time, do nothing if the right is confirmed successfully, and delete the element if it fails.

To try this out, take the collapsed-menu button at the top, beader-bar.vue

<template>
  <div class="header-bar">
    <sider-trigger v-auth="'admin'" :collapsed="collapsed" icon="md-menu" @on-change="handleCollpasedChange"></sider-trigger>
    ...
  </div>
</template>
Copy the code

Displays the button when v-auth=”‘admin'”, hides the button if it is user.

Custom Auth component

This can also be done by customizing the Auth component, creating a functional component auth.vue

<script>
import store from '@/store'
export default {
  functional: true,
  props: {
    authority: {
      type: String,
      require: true
    }
  },
  render (h, context) {
    const { props, scopedSlots } = context
    const access = store.state.user.access
    return access.indexOf(props.authority) > -1 ? scopedSlots.default() : null
  }
}
</script>
Copy the code

Slot is returned if the validation is successful, otherwise null is returned so that the element wrapped by Auth is not displayed. Then register auth.vue as a global component so you don’t have to import it every time you use it. Edit the main js

Vue.component('Auth',Auth) import Auth from '_c/ Auth /auth.vue'Copy the code

When using directly with auth package components can be

<template>
  <div class="header-bar">
    <Auth authority="user">
      <sider-trigger :collapsed="collapsed" icon="md-menu" @on-change="handleCollpasedChange"></sider-trigger>
    </Auth>
  </div>
</template>
Copy the code

conclusion

Both written by component type and custom instructions can be implemented, component way to write the code more, more flexible with a custom command, in addition there is a little different, custom instructions made by failure, is the element directly deleted, so at this point if again by the admin user instead, element or not shown, because has been removed, You have to refresh the page to get it to show up, but not if it’s a component, flexible response. This generally doesn’t matter much.

Note that I set Access to a String, or an array. The hasOneOf method that comes with iView works fine

/** * @param {Array} target Target Array * @param {Array} arr Array to be queried * @description Checks whether the Array to be queried contains at least one element in the target Array */ export const hasOneOf = (targetarr, arr) => { return targetarr.some(_ => arr.indexOf(_) > -1) }Copy the code