大道至简,新一代企业应用无栈开发

平台之上,一种语言,可视化、脚本化、全端一体化开发

权限管理

用户、授权、权限检查

docutils document without title

可以为用户或者群组,对内容进行授权:

  • 对上层容器的授权,子层内容会自动会继承。
  • 通过为用户或群组,分配角色的方式来授权。每个角色对应一组权限。

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.1.2   unset_role

同上,取消本层授予或者禁止的角色:

obj.acl.unset_role(role_id, pid)

2.1.3   deny_role

同上,禁止上层授予的角色:

obj.acl.deny_role(role_id, pid)

2.1.4   allow_inherit_roles

或者,直接禁止上层所有的授权(v7.4):

obj.acl.allow_inherit_roles = False

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.3.2   principal_roles

得到某个用户在obj上的所有角色:

obj.acl.principal_roles(user_id)

2.3.3   inherited_role_principals

得到上层以及全局的授权信息:

obj.acl.inherited_role_principals(role_id)

2.3.4   inherited_principal_roles

得到某个用户在上层继承的角色:

obj.acl.inherited_principal_roles(user_id)

2.4   高级:调整role和权限的映射关系

2.4.1   grant_role_permission

给角色追加权限:

obj.acl.grant_role_permission(role, permisison)

2.4.2   deny_role_permission

禁止上层授予的权限:

obj.acl.deny_role_permission(role, permission)

2.4.3   unset_role_permission

去除本层授予或者禁止的权限:

obj.acl.unset_role_permission(role, permission)

2.4.4   permission_roles

读取权限对应的角色:

obj.acl.permission_roles(permission, inherit=False)

其中:

  • permission:权限的名字
  • inherit:是否返回上层继承的,False只返回obj自身的设置

返回的结构是 [(role, setting)] ,setting可以是 Allow/Deny

2.4.5   roles_permissions

查看调整的角色权限映射关系:

obj.acl.roles_permissions()

2.5   高级:直接授权

2.5.1   grant_permissoin

直接给某个用户或组授权:

obj.acl.grant_permissoin(permission, pid)

2.5.2   deny_permission

禁止上层授权:

obj.acl.deny_permission(permission, pid)

2.5.3   unset_permission

去除本层授予或者禁止的权限:

obj.acl.unset_permission(permission, pid)

2.5.4   permission_pids

查看所有的直接授权:

obj.acl.permission_pids(permission)

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地址授权