npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

sunny-rbac

v0.1.2

Published

![npm version](https://img.shields.io/npm/v/sunny-rbac) ![npm downloads](https://img.shields.io/npm/dm/sunny-rbac) ![license](https://img.shields.io/npm/l/sunny-rbac)

Downloads

2

Readme

sunny-rbac

npm version npm downloads license

页面和页面内操作的提供权限控制支持

Installation

使用npm安装

npm i sunny-rbac

使用yarn安装

yarn add sunny-rbac

使用pnpm安装

pnpm add sunny-rbac

Usages

集成用例

与可拔插路由模块(sunny-pluggable-router)集成

使用自定义路由组件 AuthRoute

import { implement as routerImplement } from 'sunny-pluggable-router'
import { AuthRoute } from 'sunny-auth'
import { Route } from 'react-router'
import hashHistory from '../hashHistory'

/**
 * 扩充 RouteConfig 类型增加auth属性
 */
declare module 'sunny-pluggable-router/dist/types/index.es' {
  interface RouteConfig {
    auth?: boolean
  }
}

/**
 * 为sunny-pluggable-router模块,使用自定义路由组件
 * 自定义选择路由组件的逻辑,可以为路由增加特别功能
 * 这里我们为路由配置增加了一个auth认证功能
 */
routerImplement({
  customRoute: route => {
    const isAdmin = true
    if (isAdmin) {
      // 适用于后台管理,后台管理项目默认启用认证路由
      // eslint-disable-next-line @typescript-eslint/no-unnecessary-boolean-literal-compare
      return route.auth === false ? Route : AuthRoute
    } else {
      // 适用于前端web应用
      return route.auth ? AuthRoute : Route
    }
  },
})

实现认证逻辑

// 实现基本的登录认证
import { implement as AuthImplement } from 'sunny-auth'

AuthImplement({
  authenticate: () => (isLogin() ? Promise.resolve() : Promise.reject()),
  requireLogin: () => {
    const pathname = routeConfig('login')?.path.toString()
    const from = hashHistory.location
    if (pathname && pathname !== from.pathname) {
      console.debug('forward to ', location, ' from ', from)
      hashHistory.push(pathname)
    }
  },
})

与授权路由模块集成

实现访问控制逻辑

import { implement as AuthImplement } from 'sunny-auth'
import {
  getPrivileges,
  getResources,
  hasResource,
  implement as RBACImplement,
} from 'sunny-rbac'
import { matchPath } from 'react-router'
import hashHistory from '../hashHistory'

RBACImplement({
  // 因用例代码使用了hash history而不是browser history,所以这里重写了模块获取location.pathname的默认逻辑
  currentResource: () => hashHistory.location.pathname,
})

AuthImplement({
  authorize: routeProps =>
    Promise.all([
      // 准备好RBAC权限控制模块所需的resources资源信息,后面的查询都会用到
      getResources()
        // 准备好RBAC权限控制模块当前resources所需的privileges信息
        .then(() => getPrivileges())
        .then(() => {
          /**
           * 使用matchPath是为了处理route.path为数组的情况
           */
          const match = matchPath(hashHistory.location.pathname, routeProps)
          /**
           * 查询当前菜单是否被授权访问
           * 如果/parent被允许,那么/parent/child也被允许
           */
          return (match && hasResource(match.path)) || Promise.reject()
        }),
    ]),
  deny: () => {
    console.debug(
      'The visitor is not allowed to go',
      hashHistory.location,
      '. Then go back.'
    )
  },
})

配置 sunny-rbac,对接后台权限系统接口。

import { implement as RBACImplement, clearCache } from 'sunny-rbac'

RBACImplement({
  // 向后端权限系统查询所有可用资源
  getResources: () => Promise.resolve([{ path: '/dashboard', id: 1 }]),
  // 向后端权限系统查询某个资源所有可用权限
  // 在运行时会用户的访问某些页面的行为而被调用
  getPrivileges: (/* { id: resourceId } */) => Promise.resolve([{ title: '操作名称' }]),
  // 查询用户是否为超级管理员,超管为上帝视角,拥有最高权力。所有权限查询都会通过
  isRootUser() {
    // roleId  === 1   超级管理员
    const roleId = 1
    return Number(roleId) === 1
  },
})

// 权限信息更新时,清空现有缓存,可以触发重新请求权限数据
// onPrivilegeUpdated(clearCache)
// onRequestLogin(clearCache)
// onSessionError(clearCache)
// onLogout(clearCache)

更多用例代码见 examplesstorybook 文档

How it works

介绍当前项目与后端 RBAC 模型权限系统对接在一起的协作方式。

术语表

| 术语 | 别名 | 翻译 | |------|-------|-----------------------------------| | 一级权限 | 页面/资源 | 以页面为单位。体现为页面、页面路由、侧栏菜单 | | 二级权限 | 操作/权限 | 以可用操作为单位。体现为页面中的单个按钮、一组交互组件、一个逻辑块 |

一级权限

整个页面

整个页面

页面路由

/sys/firstAuth

侧栏菜单

侧栏菜单

二级权限

单个按钮

单个按钮

一组交互组件

一组交互组件

可以将这一组交互组件命名为“搜索”,意思为只要有“搜索”权限,即可以使用 这一组组件。

一个逻辑块

import { hasPrivilege } from 'sunny-rbac'
if (hasPrivilege('合计')) {
  // do something else
}

了解协作方式

协作方式概述

先对路由访问进行控制,在对页面操作进行控制。 一个页面是否能访问,除了要检查登录态,还得检查路由对于当前用户来讲是否有权访问。 好在现在,可以利用自定义路由模块实现拦截、登录态查询、访问权限查询。

为了实现这些想法,设计了认证授权路由组件(sunny-auth), 权限控制模块(sunny-rbac)两个关键模块。 sunny-auth 用来路由拦截。sunny-rbac 用来提供对访问权限查询服务。

先了解一下基本工作流程。

页面访问控制流程

通用流程

访问路由 > 拦截访问 > 身份认证

正常流程

认证通过 > 允许访问

异常流程

认证失败 > 拒绝访问
页面操作控制流程

通用流程

操作权限 > 读取 > 查询

正常流程

有 > 通过 > 展示

异常流程

没有 > 拒绝 > 隐藏

在后台管理页面开发中的应用

新开发好的页面,通常已经定义好了路由信息,接下来就需要加入侧栏菜单,和为页面添加可用操作。

将新页面加入菜单

功能定位:权限路由 > 添加

将新页面加入菜单

为新页面添加可用操作权限

功能定位:权限路由 > 找到已添加的新页面 > 新增权限

为新页面添加可用操作权限

注意“权限路由”处填写接口地址

根据页面的功能设计,将剩余的“操作”依次加入

Browser Compatibility

浏览器兼容性

Changelog

See CHANGELOG.md