0.0.3 • Published 2 years ago

sunny-acl v0.0.3

Weekly downloads
-
License
MIT
Repository
-
Last release
2 years ago

sunny-acl

npm version npm downloads license

基于 acljs 进行再封装,在原有功能基础上,提供根据 路由path 收集 resources 能力。

Installation

使用npm安装

npm i sunny-acl

使用yarn安装

yarn add sunny-acl

使用pnpm安装

pnpm add sunny-acl

Usages

集成用例

为react router的Router组件定一个共享history实例,后面方便和认证路由进行协同工作。 hashHistory.ts 文件内容为

import { createHashHistory } from 'history'
export default createHashHistory()

实现认证与授权逻辑。 integrate.ts 文件内容为

import { implement as AuthImplement } from 'sunny-auth'
import { Action, implement as ACLImplement, isAllowed } from 'sunny-acl'
import hashHistory from './hashHistory'

ACLImplement({
  ajaxPermissions: () =>
    Promise.resolve({
      roles: [
        { name: 'guest' },
        { name: 'member', parent: 'guest' },
        { name: 'admin' },
      ],
      resources: [{ name: 'home' }],
      rules: [
        {
          access: 'allow',
          role: 'admin',
          privileges: null,
          resources: null,
        },
        {
          access: 'allow',
          role: 'member',
          privileges: null,
          resources: ['home'],
        },
      ],
    }),
  getRole: () => sessionStorage.getItem('role'),
  getPaths: () => ['/dashboard'] // 如果有条件,可以将所有页面路由path集合在一起生成 resources
})

AuthImplement({
  authenticate: () => {
    const isLogin = () => {
      return sessionStorage.getItem('token')
        ? Promise.resolve()
        : Promise.reject()
    }
    return isLogin()
  },
  requireLogin: () => {
    hashHistory.push('/login')
  },
  authorize: isAllowed,
  deny: () => {
    console.debug('You are not allowed to go', history.location.pathname)
    alert('拒绝访问')
    hashHistory.goBack()
  },
})

使用路由组件拦截访问

import React, { FC } from 'react'
import { Router, Route, Switch } from 'react-router'
import { AuthRoute } from 'sunny-auth'
import { Action } from 'sunny-acl'
import hashHistory from './hashHistory'
import './integrate.ts' // 载入配置逻辑,使认证逻辑正常工作

declare module 'react-router' {
  interface RouteProps extends Action {}
}

const App: FC = () => (
  <Router history={hashHistory}>
    <Switch>
      <AuthRoute path={'/'} exact resource="home">Home Page</AuthRoute>
      <AuthRoute path={'/dashboard'}>Dashboard Page</AuthRoute>
      <Route path={'/login'}>
        Login Page
        <button onClick={() => {
          sessionStorage.setItem('token', 'xxx')
          // 随机设定一个角色
          sessionStorage.setItem('role', ['member', 'admin'].sort(() => .5 - Math.random()).pop())
          hashHistory.goBack()
        }}>登录</button>
      </Route>
    </Switch>
  </Router>
)

更多集成用例

将权限规则与组件、代码块进行关联

假设权限配置如下所示

import { Permissions } from 'sunny-acl'
const permissions: Permissions = {
  roles: [
    // ...
    { name: 'manager' },
    // ...
  ],
  resources: [
    // ...
    { name: 'product' }
    // ...
  ],
  rules: [
    // ...
    {
      access: 'allow',
      role: 'manager',
      privileges: ['add', 'delete'],
      resources: ['product'],
    },
    // ...
  ],
}

与组件绑定

import React, { FC } from 'react'
import { Privilege } from 'sunny-acl'

const Components: FC = () => <>
  <Privilege path="product/add"><button>添加</button></Privilege>
  <Privilege resource="product" privilege="delete"><button>删除</button></Privilege>
</>

与逻辑块关联

import React, { useEffect, FC } from 'react'
import { isAllowedSync } from 'sunny-acl'

const Components: FC = () => {
  useEffect(() => {
    if (isAllowedSync({ path: 'product/add' })) {
      // do something else
    }
  }, [])
  return <></>
}

How it works

资源和权限是集中声明,还是分散写在路由配置中?

集中和分散方式之间的比较

  • 资源和权限是集中声明
    • 由path解析器决定当前路由的resource、privilege信息
      • 无法提取信息时可以由路由配置作为补充
    • 需要预先定义ACL权限列表
      • 既然会由后端存储,那么分散写到路由配置中就不是个好的选择
  • 分散写在路由配置中
    • 由路由嵌套关系决定resource继承关系
    • 由路由决定当前是resource还是privilege
    • 需要遍历树形结构路由信息表来生成resource继承关系

最终决定

  • 考虑未来权限信息由后端存储,可以考虑先集中声明
  • path解析器作为确认resource、privilege主要方式,路由配置中携带这两个字段作为覆盖/补充
    • route path可以确定resource继承关系,确定privilege
      • 如果选择自动生成,无论是否为继承关系,resource关键词都不可以重复出现
  • 如果想要生成resources所有资源信息,可以遍历所有路由配置,结合path解析器后生成

Browser Compatibility

浏览器兼容性

Changelog

See CHANGELOG.md