refactor permission
This commit is contained in:
		@@ -79,8 +79,7 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    async logout() {
 | 
			
		||||
      await this.$store.dispatch('user/logout')
 | 
			
		||||
      // In order to re-instantiate the vue-router object to avoid bugs
 | 
			
		||||
      location.reload()
 | 
			
		||||
      this.$router.push(`/login?redirect=${this.$route.fullPath}`)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,66 +7,64 @@ import { getToken } from '@/utils/auth' // get token from cookie
 | 
			
		||||
 | 
			
		||||
NProgress.configure({ showSpinner: false }) // NProgress Configuration
 | 
			
		||||
 | 
			
		||||
// permission judge function
 | 
			
		||||
function hasPermission(roles, permissionRoles) {
 | 
			
		||||
  if (roles.includes('admin')) return true // admin permission passed directly
 | 
			
		||||
  if (!permissionRoles) return true
 | 
			
		||||
  return roles.some(role => permissionRoles.indexOf(role) >= 0)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist
 | 
			
		||||
 | 
			
		||||
router.beforeEach((to, from, next) => {
 | 
			
		||||
  NProgress.start() // start progress bar
 | 
			
		||||
  if (getToken()) {
 | 
			
		||||
    // determine if there has token
 | 
			
		||||
router.beforeEach(async(to, from, next) => {
 | 
			
		||||
  // start progress bar
 | 
			
		||||
  NProgress.start()
 | 
			
		||||
 | 
			
		||||
    /* has token*/
 | 
			
		||||
  // determine whether the user has logged in
 | 
			
		||||
  const hasToken = getToken()
 | 
			
		||||
 | 
			
		||||
  if (hasToken) {
 | 
			
		||||
    if (to.path === '/login') {
 | 
			
		||||
      // if is logged in, redirect to the home page
 | 
			
		||||
      next({ path: '/' })
 | 
			
		||||
      NProgress.done() // if current page is dashboard will not trigger	afterEach hook, so manually handle it
 | 
			
		||||
      NProgress.done()
 | 
			
		||||
    } else {
 | 
			
		||||
      if (store.getters.roles.length === 0) {
 | 
			
		||||
        // 判断当前用户是否已拉取完user_info信息
 | 
			
		||||
        store
 | 
			
		||||
          .dispatch('user/getInfo')
 | 
			
		||||
          .then(res => {
 | 
			
		||||
            // 拉取user_info
 | 
			
		||||
            const { roles } = res // note: roles must be a object array! such as: [{id: '1', name: 'editor'}, {id: '2', name: 'developer'}]
 | 
			
		||||
            store.dispatch('permission/generateRoutes', { roles }).then(accessRoutes => {
 | 
			
		||||
              // 根据roles权限生成可访问的路由表
 | 
			
		||||
              router.addRoutes(accessRoutes) // 动态添加可访问路由表
 | 
			
		||||
              next({ ...to, replace: true }) // hack方法 确保addRoutes已完成 ,set the replace: true so the navigation will not leave a history record
 | 
			
		||||
            })
 | 
			
		||||
          })
 | 
			
		||||
          .catch(err => {
 | 
			
		||||
            store.dispatch('user/resetToken').then(() => {
 | 
			
		||||
              Message.error(err)
 | 
			
		||||
              next({ path: '/' })
 | 
			
		||||
            })
 | 
			
		||||
          })
 | 
			
		||||
      } else {
 | 
			
		||||
        // 没有动态改变权限的需求可直接next() 删除下方权限判断 ↓
 | 
			
		||||
        if (hasPermission(store.getters.roles, to.meta.roles)) {
 | 
			
		||||
      // determine whether the user has obtained his permission roles through getInfo
 | 
			
		||||
      const hasRoles = store.getters.roles && store.getters.roles.length > 0
 | 
			
		||||
      if (hasRoles) {
 | 
			
		||||
        next()
 | 
			
		||||
      } else {
 | 
			
		||||
          next({ path: '/401', replace: true, query: { noGoBack: true }})
 | 
			
		||||
        try {
 | 
			
		||||
          // get user info
 | 
			
		||||
          // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
 | 
			
		||||
          const { roles } = await store.dispatch('user/getInfo')
 | 
			
		||||
 | 
			
		||||
          // generate accessible routes map based on roles
 | 
			
		||||
          const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
 | 
			
		||||
 | 
			
		||||
          // dynamically add accessible routes
 | 
			
		||||
          router.addRoutes(accessRoutes)
 | 
			
		||||
 | 
			
		||||
          // hack method to ensure that addRoutes is complete
 | 
			
		||||
          // set the replace: true, so the navigation will not leave a history record
 | 
			
		||||
          next({ ...to, replace: true })
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
          // remove token and go to login page to re-login
 | 
			
		||||
          await store.dispatch('user/resetToken')
 | 
			
		||||
          Message.error(error || 'Has Error')
 | 
			
		||||
          next(`/login?redirect=${to.path}`)
 | 
			
		||||
          NProgress.done()
 | 
			
		||||
        }
 | 
			
		||||
        // 可删 ↑
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    /* has no token*/
 | 
			
		||||
 | 
			
		||||
    if (whiteList.indexOf(to.path) !== -1) {
 | 
			
		||||
      // 在免登录白名单,直接进入
 | 
			
		||||
      // in the free login whitelist, go directly
 | 
			
		||||
      next()
 | 
			
		||||
    } else {
 | 
			
		||||
      next(`/login?redirect=${to.path}`) // 否则全部重定向到登录页
 | 
			
		||||
      NProgress.done() // if current page is login will not trigger afterEach hook, so manually handle it
 | 
			
		||||
      // other pages that do not have permission to access are redirected to the login page.
 | 
			
		||||
      next(`/login?redirect=${to.path}`)
 | 
			
		||||
      NProgress.done()
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
router.afterEach(() => {
 | 
			
		||||
  NProgress.done() // finish progress bar
 | 
			
		||||
  // finish progress bar
 | 
			
		||||
  NProgress.done()
 | 
			
		||||
})
 | 
			
		||||
 
 | 
			
		||||
@@ -105,12 +105,6 @@ export const constantRoutes = [
 | 
			
		||||
  }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
export default new Router({
 | 
			
		||||
  // mode: 'history', // require service support
 | 
			
		||||
  scrollBehavior: () => ({ y: 0 }),
 | 
			
		||||
  routes: constantRoutes
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
export const asyncRoutes = [
 | 
			
		||||
  {
 | 
			
		||||
    path: '/permission',
 | 
			
		||||
@@ -383,3 +377,19 @@ export const asyncRoutes = [
 | 
			
		||||
 | 
			
		||||
  { path: '*', redirect: '/404', hidden: true }
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
const createRouter = () => new Router({
 | 
			
		||||
  // mode: 'history', // require service support
 | 
			
		||||
  scrollBehavior: () => ({ y: 0 }),
 | 
			
		||||
  routes: constantRoutes
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const router = createRouter()
 | 
			
		||||
 | 
			
		||||
// Detail see: https://github.com/vuejs/vue-router/issues/1234#issuecomment-357941465
 | 
			
		||||
export function resetRouter() {
 | 
			
		||||
  const newRouter = createRouter()
 | 
			
		||||
  router.matcher = newRouter.matcher // reset router
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default router
 | 
			
		||||
 
 | 
			
		||||
@@ -47,9 +47,8 @@ const mutations = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const actions = {
 | 
			
		||||
  generateRoutes({ commit }, data) {
 | 
			
		||||
  generateRoutes({ commit }, roles) {
 | 
			
		||||
    return new Promise(resolve => {
 | 
			
		||||
      const { roles } = data
 | 
			
		||||
      let accessedRoutes
 | 
			
		||||
      if (roles.includes('admin')) {
 | 
			
		||||
        accessedRoutes = asyncRoutes
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import { login, logout, getInfo } from '@/api/user'
 | 
			
		||||
import { getToken, setToken, removeToken } from '@/utils/auth'
 | 
			
		||||
import router, { resetRouter } from '@/router'
 | 
			
		||||
 | 
			
		||||
const state = {
 | 
			
		||||
  token: getToken(),
 | 
			
		||||
@@ -78,6 +79,7 @@ const actions = {
 | 
			
		||||
        commit('SET_TOKEN', '')
 | 
			
		||||
        commit('SET_ROLES', [])
 | 
			
		||||
        removeToken()
 | 
			
		||||
        resetRouter()
 | 
			
		||||
        resolve()
 | 
			
		||||
      }).catch(error => {
 | 
			
		||||
        reject(error)
 | 
			
		||||
@@ -95,23 +97,26 @@ const actions = {
 | 
			
		||||
    })
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  // 动态修改权限
 | 
			
		||||
  // Dynamically modify permissions
 | 
			
		||||
  changeRoles({ commit, dispatch }, role) {
 | 
			
		||||
    return new Promise(resolve => {
 | 
			
		||||
    return new Promise(async resolve => {
 | 
			
		||||
      const token = role + '-token'
 | 
			
		||||
 | 
			
		||||
      commit('SET_TOKEN', token)
 | 
			
		||||
      setToken(token)
 | 
			
		||||
      getInfo(token).then(response => {
 | 
			
		||||
        const { data } = response
 | 
			
		||||
        const { roles, name, avatar, introduction } = data
 | 
			
		||||
        commit('SET_ROLES', roles)
 | 
			
		||||
        commit('SET_NAME', name)
 | 
			
		||||
        commit('SET_AVATAR', avatar)
 | 
			
		||||
        commit('SET_INTRODUCTION', introduction)
 | 
			
		||||
        dispatch('permission/generateRoutes', data) // 动态修改权限后 重绘侧边菜单
 | 
			
		||||
 | 
			
		||||
      const { roles } = await dispatch('getInfo')
 | 
			
		||||
 | 
			
		||||
      resetRouter()
 | 
			
		||||
 | 
			
		||||
      // generate accessible routes map based on roles
 | 
			
		||||
      const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })
 | 
			
		||||
 | 
			
		||||
      // dynamically add accessible routes
 | 
			
		||||
      router.addRoutes(accessRoutes)
 | 
			
		||||
 | 
			
		||||
      resolve()
 | 
			
		||||
    })
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -135,11 +135,12 @@ export default {
 | 
			
		||||
      this.$refs.loginForm.validate(valid => {
 | 
			
		||||
        if (valid) {
 | 
			
		||||
          this.loading = true
 | 
			
		||||
          // dispatch @/store/modules/user login action
 | 
			
		||||
          this.$store.dispatch('user/login', this.loginForm).then(() => {
 | 
			
		||||
            this.loading = false
 | 
			
		||||
          this.$store.dispatch('user/login', this.loginForm)
 | 
			
		||||
            .then(() => {
 | 
			
		||||
              this.$router.push({ path: this.redirect || '/' })
 | 
			
		||||
          }).catch(() => {
 | 
			
		||||
              this.loading = false
 | 
			
		||||
            })
 | 
			
		||||
            .catch(() => {
 | 
			
		||||
              this.loading = false
 | 
			
		||||
            })
 | 
			
		||||
        } else {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user