权限管理
用户、授权、权限检查
可以为用户或者群组,对内容进行授权:
- 对上层容器的授权,子层内容会自动会继承。
- 通过为用户或群组,分配角色的方式来授权。每个角色对应一组权限。
目录
1 基本概念
1.1 用户和组
当前登录用户可从 request.me 可得到:
- request.me.id 是当前用户的pid
- request.me.groups 是当前用户所属的组
权限管理的时候,用户和组都采用一个pid进行标识,通过前缀区分,比如:
- users. 前缀表示用户,比如 users.zhangsan
- groups.tree. 前缀表示部门组织结构树
- groups.tree.default 整个公司的内部人员
- groups.job. 前缀表示组,后面是组的ID
- groups.teams. 表示空间成员,详细见《空间成员协作》
- groups.teams.0 : 站点全部人员
- groups.teams.0-managers : 站点管理人
- groups.roles. 账户管理角色
- groups.roles.AccountAdmin 账户管理人
- groups.roles.Auditor 账户审计人
- groups.roles.custom. 岗位
- groups.roles.custom.*.Leader 所有的Leader岗位
- groups.roles.custom.default.Leader 某个部门(default)下的Leader岗位
- zope. 这个前缀是一些写内置用户和组,比如:
- zope.Authenticated (组)任意登录用户
- zope.Everybody (组)全部人员,包括登录和未登录
- zope.Anybody (组)所有未登录用户
- zope.anybody 匿名为登录用户
- zope.system 系统用户,自动任务执行使用这个用户
- zope.anybody-xxx: 临时登录的游客身份
1.2 权限
系统中常用权限,权限ID为字符串类型,下文中权限ID将用permisson_id来代替。
管理权限:
- ManageSite:管理站点,站点管理员SiteManager才能管理站点
- ManagePermission: 授权操作
- Manage:管理权限,包括文件移动、删除改名、栏目设置等
- Review: 更改状态/审批,文件夹管理员、审核人,才可以审核
- Audit:审计,可以查看操作历史
查看权限:
- Access:访问容器:文件夹、容器/栏目访问的权限。
- View:查看表单或文件标题等基本属性。
- Preview: 在线查看文件内容
- Pdf: 下载水印pdf
- Print: 打印文件
- Download: 下载文件
编辑修改权限:
- Edit:下载编辑文件,也可以对文件改名
- OnlineEdit: 在线编辑文件内容
- ChangeProp: 更改属性,包括核心属性和扩展属性
- UpdateRevision: 更改版本信息(定版)
- ManageRevision: 管理文件的历史版本,包括删除版本、回滚等。默认
- Configure: 设置内容的订阅人、标签等
添加权限:
- Add:添加文件、流程单
- AddFolder: 添加文件夹
- AddContainer: 添加容器(子栏目)
- AddRevision: 上传新版本
其他特殊权限:
- Logined: 是否登录
- Delegate: 委托
- Comment: 评论
1.3 角色 obj.allowed_roles
角色是权限的集合,为方便管理,授权实际就是分配角色。角色ID为字符串类型, 可以枚举系统对象所有的角色:
obj.allowed_roles
不同对象使用的角色不同,系统全部角色包括:
管理角色:
- SiteManager 站点管理人,只拥有ManageSite的权限,只有站点管理人才有SiteManager角色
- Manager 栏目管理人,比如文件夹、表单库的管理人,默认站点管理之外的所有权限
- Owner 文件管理人,文件的拥有者,默认拥有文件的编辑、管理权限
安全相关角色:
- Auditor: 专职审计,拥有Audit权限
- PermissionManager 专职授权人,专职负责授权,只拥有权限管理角色
容器的新建角色:
- ContainerCreator: 可以创建表单库、应用库
- Collaborator 添加文件、表单
- Creator: 可以创建文件夹
编辑相关角色:
- Editor 编辑人,可以下载文件进行编辑
- OnlineEditor: 在线编辑人,不能下载编辑
- Reviewer:审核人,可以直接改变状态
容器的查看角色
- Accessor: 文件夹访问人:进入文件夹
- Reader: 文件夹5级查看人:下载文件
- Reader4: 文件夹4级查看人:下载pdf
- Reader3: 文件夹3级查看人: 打印
- Reader2: 文件夹2级查看人: 在线查看
- Reader1:文件夹1级查看人:查看标题
文件表单查看角色:
- PrivateReader 查看表单、下载原始文件
文件的查看角色:
- PrivateReader4 文件 下载pdf
- PrivateReader3 文件 文件打印
- PrivateReader2 文件 在线查看
- PrivateReader1 文件 查看标题
流程专用角色:
- Responsible 负责人
- Delegator 委托人
1.4 状态
内容的状态,可能影响角色所包含的权限。
1.4.1 保密状态 visible
文件和表单的 visible 状态,控制上层容器的查看角色是否拥有查看权限,也就是:
- 对于角色:Reader/Reader1/Reader2/Reader3/Reader4
- 是否拥有权限:View/Preview/Pdf/Print/Download
具体:
- 非保密 visible.default: 容器的查看角色,可以查看文件
- 保密 visible.private:容器的查看角色,不可以查看文件
1.4.2 变更状态 modify
文件和表单的 modify 状态,控制文件能否被修改,也就是:
- 对于角色:Manager/Owner/Editor/OnlineEditor
- 是否拥有权限:Edit/OnlineEdit/Delete/Add/AddRevision/ChangeProp/Manage
具体:
- 草稿和废弃 modify.default / modify.abandoned
- 发布和存档 modify.archived / modify.published:禁止编辑和删除权限
- 待审状态 modify.pending :禁止编辑和删除
1.4.3 文件夹受控状态 folder
文件夹受控状态,并不改变文件夹自身的权限。但是会改变包含非正式文件的查看权限:
- 对于角色:Reader/Reader1/Reader2/Reader3/Reader4
- 对于非正式文件,也就是 modify.archived / modify.published 之外状态的文件
- 是否拥有非正式查看权限:View/Preview/Pdf/Print/Download
具体:
- 普通文件夹 folder.default: 文件夹的查看角色,可以查看非正式文件的文件
- 受控文件夹 folder.control: 文件夹的查看角色,不可查看非正式文件
2 授权
2.1 授权 acl
2.1.1 grant_role
在obj对象上,授予用户某个角色:
obj.acl.grant_role(role_id, pid)
用户一点被一旦授予角色,将在改文件上拥有角色定义的所有权限。 如果是针对容器授权,默认情况下,该用户在容器下的所有内容也拥有这个角色。
2.2 检查权限 check_permission
检查当前用户对某对象是否有某种权限,可使用 permit 方法:
obj.acl.check_permission(permission_id)
如果有该权限即返回True,反之返回False
2.3 读取权限设置
2.3.1 role_principals
根据角色来获取obj对象上拥有该角色的用户ID:
obj.acl.role_principals(role_id)
返回 [pid, setting] , 其中setting可以是 Allow, Deny
2.4 高级:调整role和权限的映射关系
2.4.4 permission_roles
读取权限对应的角色:
obj.acl.permission_roles(permission, inherit=False)
其中:
- permission:权限的名字
- inherit:是否返回上层继承的,False只返回obj自身的设置
返回的结构是 [(role, setting)] ,setting可以是 Allow/Deny
2.6 示例:禁止调整归档状态
目前文件夹管理人(Manager)和审核人(Reviewer)是可以调整文件归档状态的。
但是一旦公司统一采用流程进行管控,就禁止手工调整文件的归档状态,可以通过下面的脚本禁止:
root.acl.deny_role_permission('Manager', 'Review') root.acl.deny_role_permission('Reviewer', 'Review')
禁止系统的分享权限:
root.acl.deny_role_permission('Reviewer', 'Review')
3 常用人员和自建分组
通过人员选择组件,每个人可以记录自己的常用人员。
我的常用人员:
>>> root.profiles.get(request.me.pid).get('contacts_recent_pids') ['users.pan', 'users.lisi', 'users.wang']
我最近使用的组:
>>> root.profiles.get(request.me.pid).get('contacts_recent_groups') [{'users.pan', 'users.zhang'}, {'users.li', 'users.wang'}]
我自定义的组:
>>> root.profiles.get(request.me.pid).get('contacts_named_groups') {'groupid1':{'title':'组1', 'pids':['users.li', 'users.wang']}, 'groupid2':{'title':'组2', 'pids':['users.zhong', 'users.jack']}, }
4 站点安全策略 IPermissionPolicy
可以设置站点的安全策略,限制指定位置、对某些权限,设定额外的生效条件,包括:
- 所在IP范围
- 人员范围
- 额外的任意脚本
使用 IPermissionPolicy 进行设置(系统有安全策略设置软件包提供使用). 查看安全策略:
IPermissionPolicy(root).list_policy()
设置安全策略:
IPermissionPolicy(root).replace_policy([{ 'obj': [12312], # 对象位置 'scope': 'scope_subtree|scope_base|scope_one_level', # 范围 'permissions':['zopen.Reader1', 'zopen.Reader2'], # 权限 'opr':'and|or', # IP地址,人员条件是否同时满足 'ipranges':[], # IP地址范围 'pids':[], # 许可的人员 'expresson': '', 附加的表达式 'enabled': True, 是否使用本规则 }])
其中expression,是一个包含 request obj 变量的表达式,用于动态计算。
本API的使用,可以参见应用: IP地址授权