Documentation
¶
Overview ¶
Package perm 定义权限串、内置角色与所有权规则。
权限串格式为 <资源>:<动作>,动词统一为 write / write_any / publish / delete_any / manage。 `_any` 后缀表示「不限所有权」;不带后缀的权限只能操作自己拥有的对象。
Index ¶
Constants ¶
const ( RoleSuperAdmin = "super-admin" RoleAdmin = "admin" RoleEditor = "editor" // RoleMember 是前台自助注册账号的角色,见 BuiltinRoles 中的说明。 RoleMember = "member" )
内置角色名。
2026-09-15 站长把内置角色收成三挡:用户 / 编辑 / 管理员,外加不对站长开放的 super-admin。原先的 author(只能写自己的、不能发布)取消——它的活由自定义角色承担, 命令行的 create-user 也不再默认落在这个角色上。
Variables ¶
var All = []Permission{ PostsWrite, PostsWriteAny, PostsPublish, PostsDeleteAny, PagesWrite, PagesWriteAny, PagesPublish, PagesDeleteAny, TaxonomiesManage, CommentsManage, CommentsManageAny, MediaWrite, MediaDeleteAny, ContentUnsafeHTML, MenusManage, UsersManage, RolesManage, ThemesManage, SettingsManage, ExtensionsManage, PluginsManage, SiteDelete, SiteTransfer, }
All 是全部合法权限串,顺序固定以便生成稳定的角色定义与 UI 列表。
var BuiltinRoleMeta = map[string]RoleMeta{ RoleSuperAdmin: { Label: "超级管理员", Description: "站点的最高权限,含删除站点与转移所有权。不对外开放:不可修改、不可删除,也不出现在角色管理页", }, RoleAdmin: { Label: "管理员", Description: "除删除站点与转移所有权外的全部权限,含用户、角色、设置、主题与插件", }, RoleEditor: { Label: "编辑", Description: "内容全权:可改可发他人内容、删任何人的文章,并管理分类标签、评论与附件;不碰用户、角色、设置、主题、菜单与插件", }, RoleMember: { Label: "用户", Description: "前台注册账号:能登录前台、能被内容与评论归属,但没有任何后台权限", }, }
BuiltinRoleMeta 是内置角色的显示名与描述。
显示名与描述**随代码走**(每次启动覆盖),权限集合**归站长**(只在角色首次创建时写入)。 两者分开的理由:措辞是产品的一部分,升级就该更新;而权限是站长在新版权限清单下的 选择,一次升级把它覆盖回去,就会在无声中放宽或收紧一个正在用的角色。
var BuiltinRoleNames = []string{RoleSuperAdmin, RoleAdmin, RoleEditor, RoleMember}
BuiltinRoleNames 是内置角色名,按权限从大到小排列。
var BuiltinRoles = map[string][]Permission{ RoleSuperAdmin: All, RoleAdmin: { PostsWrite, PostsWriteAny, PostsPublish, PostsDeleteAny, PagesWrite, PagesWriteAny, PagesPublish, PagesDeleteAny, TaxonomiesManage, CommentsManage, CommentsManageAny, MediaWrite, MediaDeleteAny, ContentUnsafeHTML, MenusManage, UsersManage, RolesManage, ThemesManage, SettingsManage, ExtensionsManage, PluginsManage, }, RoleEditor: { PostsWrite, PostsWriteAny, PostsPublish, PostsDeleteAny, PagesWrite, PagesWriteAny, PagesPublish, PagesDeleteAny, TaxonomiesManage, CommentsManage, CommentsManageAny, MediaWrite, MediaDeleteAny, }, RoleMember: {}, }
BuiltinRoles 是内置角色到其权限集合的映射。
角色即权限串的集合,允许自定义角色,故此处只是「预设」而非硬编码逻辑。 除 super-admin 外,这里给出的只是**首次创建时**的默认值,之后以库中的记录为准 (见 Store.SeedRoles);改回默认值走角色管理页的「恢复默认」。
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 EqualSets ¶
func EqualSets(a, b []Permission) bool
EqualSets 报告两组权限(忽略顺序与重复)是否相同。
用来判断一个内置角色的权限是否已被站长改过,从而决定界面上要不要提示 「已自定义」并给出「恢复默认」。与 len(a) == len(b) 这种写法相比, 它对重复项和顺序都不敏感。
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 (Permission) Action ¶
func (p Permission) Action() string
Action 返回权限串的动作部分,如 posts:write → write。
func (Permission) Resource ¶
func (p Permission) Resource() string
Resource 返回权限串的资源部分,如 posts:write → posts。
func (Permission) Valid ¶
func (p Permission) Valid() bool
Valid 报告该权限串是否在 v1 清单内。
只接受清单内的权限,避免拼错的权限串被静默当作「无权限」—— 那会让配置错误表现为难以排查的 403。
type Set ¶
type Set map[Permission]struct{}
Set 是一组权限,用于高效判定。
func RolePermissions ¶
func RolePermissions(roleNames []string, custom map[string][]Permission) Set
RolePermissions 汇总多个角色的权限并集。 未知角色被忽略:角色可能在升级过程中被删除,不应因此让请求 500。
func (Set) Allows ¶
func (s Set) Allows(p Permission, owned bool) bool
Allows 判定在给定所有权前提下,集合是否允许该权限。
规则:
- 直接持有 `<资源>:<动作>_any` ⇒ 无条件允许
- 直接持有不带 `_any` 的权限 ⇒ 仅当 owned 为真时允许
- 请求的权限本身带 `_any` ⇒ 必须直接持有,不能由基础权限升级得来
owned 表示目标对象是否属于当前用户;与所有权无关的权限(如 users:manage) 传任意值均可,因为它们只会走「直接持有」这条路径。
func (Set) HasAny ¶
func (s Set) HasAny(permissions ...Permission) bool
HasAny 报告集合是否包含任一给定权限,用于「满足其一即可」的场景。