perm

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 26, 2026 License: AGPL-3.0 Imports: 3 Imported by: 0

Documentation

Overview

Package perm 定义权限串、内置角色与所有权规则。

权限串格式为 <资源>:<动作>,动词统一为 write / write_any / publish / delete_any / manage。 `_any` 后缀表示「不限所有权」;不带后缀的权限只能操作自己拥有的对象。

Index

Constants

View Source
const (
	RoleSuperAdmin = "super-admin"
	RoleAdmin      = "admin"
	RoleEditor     = "editor"
	// RoleMember 是前台自助注册账号的角色,见 BuiltinRoles 中的说明。
	RoleMember = "member"
)

内置角色名。

2026-09-15 站长把内置角色收成三挡:用户 / 编辑 / 管理员,外加不对站长开放的 super-admin。原先的 author(只能写自己的、不能发布)取消——它的活由自定义角色承担, 命令行的 create-user 也不再默认落在这个角色上。

Variables

All 是全部合法权限串,顺序固定以便生成稳定的角色定义与 UI 列表。

View Source
var BuiltinRoleMeta = map[string]RoleMeta{
	RoleSuperAdmin: {
		Label:       "超级管理员",
		Description: "站点的最高权限,含删除站点与转移所有权。不对外开放:不可修改、不可删除,也不出现在角色管理页",
	},
	RoleAdmin: {
		Label:       "管理员",
		Description: "除删除站点与转移所有权外的全部权限,含用户、角色、设置、主题与插件",
	},
	RoleEditor: {
		Label:       "编辑",
		Description: "内容全权:可改可发他人内容、删任何人的文章,并管理分类标签、评论与附件;不碰用户、角色、设置、主题、菜单与插件",
	},
	RoleMember: {
		Label:       "用户",
		Description: "前台注册账号:能登录前台、能被内容与评论归属,但没有任何后台权限",
	},
}

BuiltinRoleMeta 是内置角色的显示名与描述。

显示名与描述**随代码走**(每次启动覆盖),权限集合**归站长**(只在角色首次创建时写入)。 两者分开的理由:措辞是产品的一部分,升级就该更新;而权限是站长在新版权限清单下的 选择,一次升级把它覆盖回去,就会在无声中放宽或收紧一个正在用的角色。

BuiltinRoleNames 是内置角色名,按权限从大到小排列。

BuiltinRoles 是内置角色到其权限集合的映射。

角色即权限串的集合,允许自定义角色,故此处只是「预设」而非硬编码逻辑。 除 super-admin 外,这里给出的只是**首次创建时**的默认值,之后以库中的记录为准 (见 Store.SeedRoles);改回默认值走角色管理页的「恢复默认」。

View Source
var ResourceLabels = map[string]string{
	"posts":      "文章",
	"pages":      "页面",
	"taxonomies": "分类与标签",
	"comments":   "评论",
	"media":      "附件",
	"content":    "正文",
	"menus":      "菜单",
	"users":      "用户",
	"roles":      "角色",
	"themes":     "主题",
	"settings":   "设置",
	"extensions": "扩展记录",
	"plugins":    "插件",
	"site":       "站点",
}

ResourceLabels 是权限资源段的中文名,供角色编辑器按资源分组时显示标题。

放在服务端而不是前端写死一份:资源段随模块增加,前端那张表漏掉一个资源时, 界面上会以英文标识出现,而没有任何东西提示「这里少了一行」—— `plugins` 就这么漏过一次(2026-09-15 修)。

Functions

func Dangerous

func Dangerous(p Permission) bool

Dangerous 报告该权限是否属于高危权限。

func EqualSets

func EqualSets(a, b []Permission) bool

EqualSets 报告两组权限(忽略顺序与重复)是否相同。

用来判断一个内置角色的权限是否已被站长改过,从而决定界面上要不要提示 「已自定义」并给出「恢复默认」。与 len(a) == len(b) 这种写法相比, 它对重复项和顺序都不敏感。

func IsBuiltin

func IsBuiltin(name string) bool

IsBuiltin 报告角色名是否为内置角色。

内置角色的**名字**不可更改、角色不可删除:名字是权限判定与播种用的键, 删掉它下一次启动又会补回来,只会让人以为删除没生效。权限集合自 2026-09-15 起可改, 但 super-admin 例外——它整条都不对外开放(见 Locked)。

func Locked

func Locked(name string) bool

Locked 报告该角色是否不对站长开放。

锁定的角色既不可改也不可删,且不在角色管理页出现(仍可分配给用户): 把 super-admin 的权限改坏或把它删掉,等于让站点失去唯一的后门。

Types

type Permission

type Permission string

Permission 是一条权限串。

const (
	PostsWrite     Permission = "posts:write"
	PostsWriteAny  Permission = "posts:write_any"
	PostsPublish   Permission = "posts:publish"
	PostsDeleteAny Permission = "posts:delete_any"

	PagesWrite     Permission = "pages:write"
	PagesWriteAny  Permission = "pages:write_any"
	PagesPublish   Permission = "pages:publish"
	PagesDeleteAny Permission = "pages:delete_any"

	TaxonomiesManage Permission = "taxonomies:manage"

	CommentsManage    Permission = "comments:manage"
	CommentsManageAny Permission = "comments:manage_any"

	MediaWrite     Permission = "media:write"
	MediaDeleteAny Permission = "media:delete_any"

	// ContentUnsafeHTML 允许正文中的任意 HTML 原样输出到前台(含 iframe 与脚本钩子)。
	//
	// 这是高风险权限,默认只给管理员及以上:未净化的正文会在**站点同源**执行,
	// 而管理 API 与访客页面同源,一段脚本就能以访客(可能是管理员)的身份
	// 调用管理接口。没有这个权限的编辑者,正文在保存时会被允许列表净化。
	ContentUnsafeHTML Permission = "content:unsafe_html"

	MenusManage    Permission = "menus:manage"
	UsersManage    Permission = "users:manage"
	RolesManage    Permission = "roles:manage"
	ThemesManage   Permission = "themes:manage"
	SettingsManage Permission = "settings:manage"

	ExtensionsManage Permission = "extensions:manage"
	PluginsManage    Permission = "plugins:manage"

	SiteDelete   Permission = "site:delete"
	SiteTransfer Permission = "site:transfer"
)

v1 权限清单。

func Parse

func Parse(s string) (Permission, error)

Parse 校验并返回权限串。

func (Permission) Action

func (p Permission) Action() string

Action 返回权限串的动作部分,如 posts:write → write。

func (Permission) IsAny

func (p Permission) IsAny() bool

IsAny 报告该权限是否不限所有权。

func (Permission) Resource

func (p Permission) Resource() string

Resource 返回权限串的资源部分,如 posts:write → posts。

func (Permission) String

func (p Permission) String() string

String 实现 fmt.Stringer。

func (Permission) Valid

func (p Permission) Valid() bool

Valid 报告该权限串是否在 v1 清单内。

只接受清单内的权限,避免拼错的权限串被静默当作「无权限」—— 那会让配置错误表现为难以排查的 403。

type RoleMeta

type RoleMeta struct {
	Label       string
	Description string
}

RoleMeta 是内置角色的展示信息。

type Set

type Set map[Permission]struct{}

Set 是一组权限,用于高效判定。

func NewSet

func NewSet(permissions ...Permission) Set

NewSet 由权限列表构造集合,自动忽略重复项。

func RolePermissions

func RolePermissions(roleNames []string, custom map[string][]Permission) Set

RolePermissions 汇总多个角色的权限并集。 未知角色被忽略:角色可能在升级过程中被删除,不应因此让请求 500。

func (Set) Add

func (s Set) Add(permissions ...Permission)

Add 并入若干权限。

func (Set) Allows

func (s Set) Allows(p Permission, owned bool) bool

Allows 判定在给定所有权前提下,集合是否允许该权限。

规则:

  • 直接持有 `<资源>:<动作>_any` ⇒ 无条件允许
  • 直接持有不带 `_any` 的权限 ⇒ 仅当 owned 为真时允许
  • 请求的权限本身带 `_any` ⇒ 必须直接持有,不能由基础权限升级得来

owned 表示目标对象是否属于当前用户;与所有权无关的权限(如 users:manage) 传任意值均可,因为它们只会走「直接持有」这条路径。

func (Set) Has

func (s Set) Has(p Permission) bool

Has 报告集合是否直接包含该权限。

func (Set) HasAny

func (s Set) HasAny(permissions ...Permission) bool

HasAny 报告集合是否包含任一给定权限,用于「满足其一即可」的场景。

func (Set) List

func (s Set) List() []Permission

List 返回排序后的权限列表,便于稳定输出与断言。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL