[Feature] 授权规则添加 actions 选项,控制用户对资产的操作行为 (#2610)

* [Feature] 1. perms actions - 添加 Action Model

* [Feature] 2. perms actions - 添加 Action API

* [Feature] 3. perms actions - 授权规则: 添加actions字段

* [Feature] 4. perms actions - 授权规则创建页面: 设置 actions 默认 all

* [Feature] 5. perms actions - 资产授权工具: 动态给system_user设置actions属性; 修改授权相关的API-serializer类: 添加actions字段值

* [Feature] 6. perms actions - 更新API(用户使用系统用户连接资产时权限校验): 添加actions校验

* [Feature] 7. perms actions - 迁移文件中为已经存在的perms添加默认的action

* [Feature] 8. perms actions - 创建授权规则时设置默认action(如果actions字段值为空)

* [Feature] 9. check actions - 修改校验用户资产权限API逻辑(添加actions校验)

* [Feature] 10. check actions - 修改注释

* [Feature] 11. check actions - 添加API: 获取用户指定资产和系统用户被授权的actions

* [Feature] 12. check actions - 添加翻译信息
pull/2617/head
BaiJiangJie 6 years ago committed by 老广
parent fc1068a9dc
commit f235e20153

@ -61,13 +61,19 @@ class AssetSystemUserSerializer(serializers.ModelSerializer):
"""
查看授权的资产系统用户的数据结构这个和AssetSerializer不同字段少
"""
actions = serializers.SerializerMethodField()
class Meta:
model = SystemUser
fields = (
'id', 'name', 'username', 'priority',
'protocol', 'comment', 'login_mode'
'protocol', 'comment', 'login_mode', 'actions',
)
@staticmethod
def get_actions(obj):
return [action.name for action in obj.actions]
class SystemUserSimpleSerializer(serializers.ModelSerializer):
"""

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: Jumpserver 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-04-15 15:34+0800\n"
"POT-Creation-Date: 2019-04-22 11:30+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
@ -36,7 +36,7 @@ msgstr "测试节点下资产是否可连接: {}"
#: assets/forms/asset.py:27 assets/models/asset.py:80 assets/models/user.py:133
#: assets/templates/assets/asset_detail.html:194
#: assets/templates/assets/asset_detail.html:202
#: assets/templates/assets/system_user_asset.html:95 perms/models.py:31
#: assets/templates/assets/system_user_asset.html:95 perms/models.py:51
#: xpack/plugins/change_auth_plan/models.py:69
msgid "Nodes"
msgstr "节点管理"
@ -73,7 +73,7 @@ msgstr "网域"
#: assets/forms/asset.py:112 assets/models/node.py:31
#: assets/templates/assets/asset_create.html:30
#: assets/templates/assets/asset_update.html:35 perms/forms.py:45
#: perms/forms.py:52 perms/models.py:84
#: perms/forms.py:55 perms/models.py:105
#: perms/templates/perms/asset_permission_list.html:57
#: perms/templates/perms/asset_permission_list.html:78
#: perms/templates/perms/asset_permission_list.html:128
@ -120,7 +120,7 @@ msgstr "选择资产"
#: assets/templates/assets/system_user_list.html:33 audits/models.py:19
#: audits/templates/audits/ftp_log_list.html:41
#: audits/templates/audits/ftp_log_list.html:71 perms/forms.py:42
#: perms/models.py:30
#: perms/models.py:50
#: perms/templates/perms/asset_permission_create_update.html:45
#: perms/templates/perms/asset_permission_list.html:56
#: perms/templates/perms/asset_permission_list.html:125
@ -164,7 +164,7 @@ msgstr "SSH网关支持代理SSH,RDP和VNC"
#: assets/templates/assets/system_user_detail.html:58
#: assets/templates/assets/system_user_list.html:29 ops/models/adhoc.py:37
#: ops/templates/ops/task_detail.html:60 ops/templates/ops/task_list.html:27
#: orgs/models.py:12 perms/models.py:27
#: orgs/models.py:12 perms/models.py:17 perms/models.py:47
#: perms/templates/perms/asset_permission_detail.html:62
#: perms/templates/perms/asset_permission_list.html:53
#: perms/templates/perms/asset_permission_list.html:72
@ -439,8 +439,8 @@ msgstr "标签管理"
#: assets/templates/assets/cmd_filter_detail.html:77
#: assets/templates/assets/domain_detail.html:72
#: assets/templates/assets/system_user_detail.html:100
#: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:15 perms/models.py:36
#: perms/models.py:89 perms/templates/perms/asset_permission_detail.html:98
#: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:15 perms/models.py:57
#: perms/models.py:110 perms/templates/perms/asset_permission_detail.html:98
#: users/models/user.py:102 users/templates/users/user_detail.html:111
#: xpack/plugins/change_auth_plan/models.py:103
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113
@ -455,7 +455,7 @@ msgstr "创建者"
#: assets/templates/assets/domain_detail.html:68
#: assets/templates/assets/system_user_detail.html:96
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:64
#: orgs/models.py:16 perms/models.py:37 perms/models.py:90
#: orgs/models.py:16 perms/models.py:58 perms/models.py:111
#: perms/templates/perms/asset_permission_detail.html:94
#: terminal/templates/terminal/terminal_detail.html:59 users/models/group.py:17
#: users/templates/users/user_group_detail.html:63
@ -483,7 +483,7 @@ msgstr "创建日期"
#: assets/templates/assets/system_user_detail.html:104
#: assets/templates/assets/system_user_list.html:37
#: assets/templates/assets/user_asset_list.html:171 ops/models/adhoc.py:43
#: orgs/models.py:17 perms/models.py:38 perms/models.py:91
#: orgs/models.py:17 perms/models.py:59 perms/models.py:112
#: perms/templates/perms/asset_permission_detail.html:102 settings/models.py:34
#: terminal/models.py:32 terminal/templates/terminal/terminal_detail.html:63
#: users/models/group.py:15 users/models/user.py:94
@ -679,6 +679,8 @@ msgstr "每行一个命令"
#: audits/templates/audits/operate_log_list.html:67
#: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64
#: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:34
#: perms/forms.py:51 perms/models.py:21 perms/models.py:53
#: perms/templates/perms/asset_permission_create_update.html:50
#: perms/templates/perms/asset_permission_list.html:60
#: settings/templates/settings/terminal_setting.html:82
#: settings/templates/settings/terminal_setting.html:104
@ -723,7 +725,7 @@ msgstr "默认资产组"
#: audits/templates/audits/password_change_log_list.html:50
#: ops/templates/ops/command_execution_list.html:35
#: ops/templates/ops/command_execution_list.html:60 perms/forms.py:36
#: perms/models.py:28
#: perms/models.py:48
#: perms/templates/perms/asset_permission_create_update.html:41
#: perms/templates/perms/asset_permission_list.html:54
#: perms/templates/perms/asset_permission_list.html:119 templates/index.html:87
@ -811,7 +813,7 @@ msgstr "登录模式"
#: assets/models/user.py:247 assets/templates/assets/user_asset_list.html:168
#: audits/models.py:20 audits/templates/audits/ftp_log_list.html:49
#: audits/templates/audits/ftp_log_list.html:72 perms/forms.py:48
#: perms/models.py:32 perms/models.py:86
#: perms/models.py:52 perms/models.py:107
#: perms/templates/perms/asset_permission_detail.html:140
#: perms/templates/perms/asset_permission_list.html:58
#: perms/templates/perms/asset_permission_list.html:79
@ -1009,7 +1011,7 @@ msgstr "自动生成密钥"
#: assets/templates/assets/asset_create.html:60
#: assets/templates/assets/asset_update.html:64
#: assets/templates/assets/gateway_create_update.html:53
#: perms/templates/perms/asset_permission_create_update.html:50
#: perms/templates/perms/asset_permission_create_update.html:53
#: terminal/templates/terminal/terminal_update.html:40
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:67
msgid "Other"
@ -1025,7 +1027,7 @@ msgstr "其它"
#: assets/templates/assets/domain_create_update.html:16
#: assets/templates/assets/gateway_create_update.html:58
#: assets/templates/assets/label_create_update.html:18
#: perms/templates/perms/asset_permission_create_update.html:80
#: perms/templates/perms/asset_permission_create_update.html:83
#: settings/templates/settings/basic_setting.html:61
#: settings/templates/settings/command_storage_create.html:79
#: settings/templates/settings/email_setting.html:62
@ -1061,7 +1063,7 @@ msgstr "重置"
#: assets/templates/assets/gateway_create_update.html:59
#: assets/templates/assets/label_create_update.html:19
#: audits/templates/audits/login_log_list.html:89
#: perms/templates/perms/asset_permission_create_update.html:81
#: perms/templates/perms/asset_permission_create_update.html:84
#: settings/templates/settings/basic_setting.html:62
#: settings/templates/settings/command_storage_create.html:80
#: settings/templates/settings/email_setting.html:63
@ -1080,7 +1082,7 @@ msgstr "重置"
#: users/templates/users/user_profile_update.html:64
#: users/templates/users/user_pubkey_update.html:77
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:72
#: xpack/plugins/interface/templates/interface/interface.html:73
#: xpack/plugins/interface/templates/interface/interface.html:74
msgid "Submit"
msgstr "提交"
@ -1165,7 +1167,7 @@ msgstr "更新认证"
#: assets/templates/assets/system_user_asset.html:350
#: users/templates/users/user_detail.html:307
#: users/templates/users/user_detail.html:334
#: xpack/plugins/interface/views.py:31
#: xpack/plugins/interface/views.py:34
msgid "Update successfully!"
msgstr "更新成功"
@ -1275,6 +1277,7 @@ msgstr "选择节点"
#: users/templates/users/user_profile.html:238
#: xpack/plugins/cloud/templates/cloud/account_create_update.html:34
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create.html:36
#: xpack/plugins/interface/templates/interface/interface.html:103
#: xpack/plugins/orgs/templates/orgs/org_create_update.html:33
msgid "Confirm"
msgstr "确认"
@ -1362,9 +1365,9 @@ msgid "Date joined"
msgstr "创建日期"
#: assets/templates/assets/asset_detail.html:154
#: assets/templates/assets/user_asset_list.html:46 perms/models.py:33
#: perms/models.py:87
#: perms/templates/perms/asset_permission_create_update.html:52
#: assets/templates/assets/user_asset_list.html:46 perms/models.py:54
#: perms/models.py:108
#: perms/templates/perms/asset_permission_create_update.html:55
#: perms/templates/perms/asset_permission_detail.html:120
#: terminal/templates/terminal/terminal_list.html:34
#: users/templates/users/_select_user_modal.html:18
@ -1504,6 +1507,7 @@ msgstr "重命名失败不能更改root节点的名称"
#: users/templates/users/user_detail.html:476
#: users/templates/users/user_group_list.html:82
#: users/templates/users/user_list.html:202
#: xpack/plugins/interface/templates/interface/interface.html:97
msgid "Are you sure?"
msgstr "你确认吗?"
@ -1520,6 +1524,7 @@ msgstr "删除选择资产"
#: users/templates/users/user_group_create_update.html:31
#: users/templates/users/user_group_list.html:86
#: users/templates/users/user_list.html:206
#: xpack/plugins/interface/templates/interface/interface.html:101
#: xpack/plugins/orgs/templates/orgs/org_create_update.html:32
msgid "Cancel"
msgstr "取消"
@ -1738,7 +1743,7 @@ msgstr "删除系统用户"
msgid "System Users Deleting failed."
msgstr "系统用户删除失败"
#: assets/templates/assets/user_asset_list.html:100
#: assets/templates/assets/user_asset_list.html:100 perms/const.py:19
msgid "Connect"
msgstr "连接"
@ -1970,7 +1975,7 @@ msgstr "登录日期"
#: ops/templates/ops/adhoc_history.html:52
#: ops/templates/ops/adhoc_history_detail.html:61
#: ops/templates/ops/command_execution_list.html:66
#: ops/templates/ops/task_history.html:58 perms/models.py:34
#: ops/templates/ops/task_history.html:58 perms/models.py:55
#: perms/templates/perms/asset_permission_detail.html:86 terminal/models.py:165
#: terminal/templates/terminal/session_list.html:78
#: xpack/plugins/change_auth_plan/models.py:246
@ -2697,7 +2702,19 @@ msgstr "命令执行"
msgid "Organization"
msgstr "组织管理"
#: perms/forms.py:39 perms/models.py:29 perms/models.py:85
#: perms/const.py:18 settings/forms.py:136
msgid "All"
msgstr "全部"
#: perms/const.py:20
msgid "Upload file"
msgstr "上传文件"
#: perms/const.py:21
msgid "Download file"
msgstr "下载文件"
#: perms/forms.py:39 perms/models.py:49 perms/models.py:106
#: perms/templates/perms/asset_permission_list.html:55
#: perms/templates/perms/asset_permission_list.html:75
#: perms/templates/perms/asset_permission_list.html:122 templates/_nav.html:14
@ -2709,22 +2726,28 @@ msgstr "组织管理"
msgid "User group"
msgstr "用户组"
#: perms/forms.py:61
#: perms/forms.py:58
msgid ""
"Tips: The RDP protocol does not support separate controls for uploading or "
"downloading files"
msgstr "提示RDP 协议不支持单独控制上传或下载文件"
#: perms/forms.py:68
msgid "User or group at least one required"
msgstr "用户和用户组至少选一个"
#: perms/forms.py:70
#: perms/forms.py:77
msgid "Asset or group at least one required"
msgstr "资产和节点至少选一个"
#: perms/models.py:35 perms/models.py:88
#: perms/models.py:56 perms/models.py:109
#: perms/templates/perms/asset_permission_detail.html:90
#: users/models/user.py:99 users/templates/users/user_detail.html:107
#: users/templates/users/user_profile.html:116
msgid "Date expired"
msgstr "失效日期"
#: perms/models.py:44 perms/models.py:97 templates/_nav.html:34
#: perms/models.py:65 perms/models.py:118 templates/_nav.html:34
msgid "Asset permission"
msgstr "资产授权"
@ -2770,7 +2793,7 @@ msgstr "添加节点"
msgid "Join"
msgstr "加入"
#: perms/templates/perms/asset_permission_create_update.html:58
#: perms/templates/perms/asset_permission_create_update.html:61
msgid "Validity period"
msgstr "有效期"
@ -2828,29 +2851,29 @@ msgstr "添加用户组"
msgid "Select user groups"
msgstr "选择用户组"
#: perms/views.py:23 perms/views.py:53 perms/views.py:68 perms/views.py:83
#: perms/views.py:118 perms/views.py:150 templates/_nav.html:31
#: perms/views.py:24 perms/views.py:56 perms/views.py:71 perms/views.py:86
#: perms/views.py:121 perms/views.py:153 templates/_nav.html:31
#: xpack/plugins/orgs/templates/orgs/org_list.html:21
msgid "Perms"
msgstr "权限管理"
#: perms/views.py:24
#: perms/views.py:25
msgid "Asset permission list"
msgstr "资产授权列表"
#: perms/views.py:54
#: perms/views.py:57
msgid "Create asset permission"
msgstr "创建权限规则"
#: perms/views.py:69 perms/views.py:84
#: perms/views.py:72 perms/views.py:87
msgid "Update asset permission"
msgstr "更新资产授权"
#: perms/views.py:119
#: perms/views.py:122
msgid "Asset permission user list"
msgstr "资产授权用户列表"
#: perms/views.py:151
#: perms/views.py:154
msgid "Asset permission asset list"
msgstr "资产授权资产列表"
@ -2982,10 +3005,6 @@ msgstr ""
msgid "Enable LDAP auth"
msgstr "启用LDAP认证"
#: settings/forms.py:136
msgid "All"
msgstr "全部"
#: settings/forms.py:137
msgid "Auto"
msgstr "自动"
@ -5231,14 +5250,37 @@ msgid "Interface settings"
msgstr "界面设置"
#: xpack/plugins/interface/templates/interface/interface.html:15
#: xpack/plugins/interface/views.py:21
#: xpack/plugins/interface/views.py:24
msgid "Interface setting"
msgstr "界面设置"
#: xpack/plugins/interface/views.py:20
#: xpack/plugins/interface/templates/interface/interface.html:73
#: xpack/plugins/interface/templates/interface/interface.html:108
#: xpack/plugins/interface/templates/interface/interface.html:115
msgid "Restore Default"
msgstr "恢复默认"
#: xpack/plugins/interface/templates/interface/interface.html:98
msgid "This will restore default Settings of the interface !!!"
msgstr "您确定要恢复默认初始化吗?"
#: xpack/plugins/interface/templates/interface/interface.html:107
#: xpack/plugins/interface/views.py:53
msgid "Restore default successfully."
msgstr "恢复默认成功!"
#: xpack/plugins/interface/templates/interface/interface.html:114
msgid "Restore default failed."
msgstr "恢复默认失败!"
#: xpack/plugins/interface/views.py:23
msgid "Interface"
msgstr "界面"
#: xpack/plugins/interface/views.py:49
msgid "It is already in the default setting state!"
msgstr "当前已经是初始化状态!"
#: xpack/plugins/license/meta.py:11 xpack/plugins/license/models.py:94
#: xpack/plugins/license/templates/license/license_detail.html:50
#: xpack/plugins/license/templates/license/license_detail.html:55
@ -5268,6 +5310,7 @@ msgid "Please Import License"
msgstr "请导入许可证"
#: xpack/plugins/license/templates/license/license_detail.html:17
#: xpack/plugins/license/templates/license/license_detail.html:56
msgid "License has expired"
msgstr "许可证已经过期"
@ -5375,24 +5418,6 @@ msgstr "创建组织"
msgid "Update org"
msgstr "更新组织"
#~ msgid "Restore Default"
#~ msgstr "恢复默认"
#~ msgid "This will restore default Settings of the interface !!!"
#~ msgstr "您确定要恢复默认初始化吗?"
#~ msgid "Restore default successfully."
#~ msgstr "恢复默认成功!"
#~ msgid "Restore default failed."
#~ msgstr "恢复默认失败!"
#~ msgid "It is already in the default setting state"
#~ msgstr "当前已经是初始化状态!"
#~ msgid "Restore default successfully"
#~ msgstr "恢复默认成功!"
#~ msgid "Sync User"
#~ msgstr "同步用户"

@ -10,7 +10,7 @@ from rest_framework.pagination import LimitOffsetPagination
from common.permissions import IsOrgAdmin
from common.utils import get_object_or_none
from ..models import AssetPermission
from ..models import AssetPermission, Action
from ..hands import (
User, UserGroup, Asset, Node, SystemUser,
)
@ -20,10 +20,16 @@ from .. import serializers
__all__ = [
'AssetPermissionViewSet', 'AssetPermissionRemoveUserApi',
'AssetPermissionAddUserApi', 'AssetPermissionRemoveAssetApi',
'AssetPermissionAddAssetApi',
'AssetPermissionAddAssetApi', 'ActionViewSet',
]
class ActionViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Action.objects.all()
serializer_class = serializers.ActionSerializer
permission_classes = (IsOrgAdmin,)
class AssetPermissionViewSet(viewsets.ModelViewSet):
"""
资产授权列表的增删改查api

@ -16,7 +16,8 @@ from common.tree import TreeNodeSerializer
from common.utils import get_logger
from orgs.utils import set_to_root_org
from ..utils import (
AssetPermissionUtil, parse_asset_to_tree_node, parse_node_to_tree_node
AssetPermissionUtil, parse_asset_to_tree_node, parse_node_to_tree_node,
check_system_user_action
)
from ..hands import (
AssetGrantedSerializer, User, Asset, Node,
@ -24,6 +25,7 @@ from ..hands import (
)
from .. import serializers
from ..mixins import AssetsFilterMixin
from ..models import Action
logger = get_logger(__name__)
@ -31,7 +33,7 @@ __all__ = [
'UserGrantedAssetsApi', 'UserGrantedNodesApi',
'UserGrantedNodesWithAssetsApi', 'UserGrantedNodeAssetsApi',
'ValidateUserAssetPermissionApi', 'UserGrantedNodeChildrenApi',
'UserGrantedNodesWithAssetsAsTreeApi',
'UserGrantedNodesWithAssetsAsTreeApi', 'GetUserAssetPermissionActionsApi',
]
@ -403,16 +405,45 @@ class ValidateUserAssetPermissionApi(UserPermissionCacheMixin, APIView):
user_id = request.query_params.get('user_id', '')
asset_id = request.query_params.get('asset_id', '')
system_id = request.query_params.get('system_user_id', '')
action_name = request.query_params.get('action_name', '')
user = get_object_or_404(User, id=user_id)
asset = get_object_or_404(Asset, id=asset_id)
system_user = get_object_or_404(SystemUser, id=system_id)
su = get_object_or_404(SystemUser, id=system_id)
action = get_object_or_404(Action, name=action_name)
util = AssetPermissionUtil(user, cache_policy=self.cache_policy)
assets_granted = util.get_assets()
if system_user in assets_granted.get(asset, []):
return Response({'msg': True}, status=200)
else:
granted_assets = util.get_assets()
granted_system_users = granted_assets.get(asset, [])
if su not in granted_system_users:
return Response({'msg': False}, status=403)
_su = next((s for s in granted_system_users if s.id == su.id), None)
if not check_system_user_action(_su, action):
return Response({'msg': False}, status=403)
return Response({'msg': True}, status=200)
class GetUserAssetPermissionActionsApi(UserPermissionCacheMixin, APIView):
permission_classes = (IsOrgAdminOrAppUser,)
def get(self, request, *args, **kwargs):
user_id = request.query_params.get('user_id', '')
asset_id = request.query_params.get('asset_id', '')
system_id = request.query_params.get('system_user_id', '')
user = get_object_or_404(User, id=user_id)
asset = get_object_or_404(Asset, id=asset_id)
su = get_object_or_404(SystemUser, id=system_id)
util = AssetPermissionUtil(user, cache_policy=self.cache_policy)
granted_assets = util.get_assets()
granted_system_users = granted_assets.get(asset, [])
_su = next((s for s in granted_system_users if s.id == su.id), None)
if not _su:
return Response({'actions': []}, status=403)
actions = [action.name for action in getattr(_su, 'actions', [])]
return Response({'actions': actions}, status=200)

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
#
from django.utils.translation import ugettext_lazy as _
__all__ = [
'PERMS_ACTION_NAME_ALL', 'PERMS_ACTION_NAME_CONNECT',
'PERMS_ACTION_NAME_DOWNLOAD_FILE', 'PERMS_ACTION_NAME_UPLOAD_FILE',
'PERMS_ACTION_NAME_CHOICES'
]
PERMS_ACTION_NAME_ALL = 'all'
PERMS_ACTION_NAME_CONNECT = 'connect'
PERMS_ACTION_NAME_UPLOAD_FILE = 'upload_file'
PERMS_ACTION_NAME_DOWNLOAD_FILE = 'download_file'
PERMS_ACTION_NAME_CHOICES = (
(PERMS_ACTION_NAME_ALL, _('All')),
(PERMS_ACTION_NAME_CONNECT, _('Connect')),
(PERMS_ACTION_NAME_UPLOAD_FILE, _('Upload file')),
(PERMS_ACTION_NAME_DOWNLOAD_FILE, _('Download file')),
)

@ -47,10 +47,17 @@ class AssetPermissionForm(OrgModelForm):
'system_users': forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('System user')}
),
'actions': forms.SelectMultiple(
attrs={'class': 'select2', 'data-placeholder': _('Action')}
)
}
labels = {
'nodes': _("Node"),
}
help_texts = {
'actions': _('Tips: The RDP protocol does not support separate '
'controls for uploading or downloading files')
}
def clean_user_groups(self):
users = self.cleaned_data.get('users')

@ -0,0 +1,33 @@
# Generated by Django 2.1.7 on 2019-04-12 07:00
from django.db import migrations, models
import uuid
def add_default_actions(apps, schema_editor):
from ..const import PERMS_ACTION_NAME_CHOICES
action_model = apps.get_model('perms', 'Action')
db_alias = schema_editor.connection.alias
for action, _ in PERMS_ACTION_NAME_CHOICES:
action_model.objects.using(db_alias).update_or_create(name=action)
class Migration(migrations.Migration):
dependencies = [
('perms', '0002_auto_20171228_0025_squashed_0009_auto_20180903_1132'),
]
operations = [
migrations.CreateModel(
name='Action',
fields=[
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('name', models.CharField(choices=[('all', 'All'), ('connect', 'Connect'), ('upload_file', 'Upload file'), ('download_file', 'Download file')], max_length=128, unique=True, verbose_name='Name')),
],
options={
'verbose_name': 'Action',
},
),
migrations.RunPython(add_default_actions)
]

@ -0,0 +1,31 @@
# Generated by Django 2.1.7 on 2019-04-12 09:17
from django.db import migrations, models
def set_default_action_to_existing_perms(apps, schema_editor):
from orgs.utils import set_to_root_org
from ..models import Action
set_to_root_org()
perm_model = apps.get_model('perms', 'AssetPermission')
db_alias = schema_editor.connection.alias
perms = perm_model.objects.using(db_alias).all()
default_action = Action.get_action_all()
for perm in perms:
perm.actions.add(default_action.id)
class Migration(migrations.Migration):
dependencies = [
('perms', '0003_action'),
]
operations = [
migrations.AddField(
model_name='assetpermission',
name='actions',
field=models.ManyToManyField(blank=True, related_name='permissions', to='perms.Action', verbose_name='Action'),
),
migrations.RunPython(set_default_action_to_existing_perms)
]

@ -7,6 +7,26 @@ from django.utils import timezone
from common.utils import date_expired_default, set_or_append_attr_bulk
from orgs.mixins import OrgModelMixin, OrgManager
from .const import PERMS_ACTION_NAME_CHOICES, PERMS_ACTION_NAME_ALL
class Action(models.Model):
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
name = models.CharField(
max_length=128, unique=True, choices=PERMS_ACTION_NAME_CHOICES,
verbose_name=_('Name')
)
class Meta:
verbose_name = _('Action')
def __str__(self):
return self.get_name_display()
@classmethod
def get_action_all(cls):
return cls.objects.get(name=PERMS_ACTION_NAME_ALL)
class AssetPermissionQuerySet(models.QuerySet):
def active(self):
@ -30,6 +50,7 @@ class AssetPermission(OrgModelMixin):
assets = models.ManyToManyField('assets.Asset', related_name='granted_by_permissions', blank=True, verbose_name=_("Asset"))
nodes = models.ManyToManyField('assets.Node', related_name='granted_by_permissions', blank=True, verbose_name=_("Nodes"))
system_users = models.ManyToManyField('assets.SystemUser', related_name='granted_by_permissions', verbose_name=_("System user"))
actions = models.ManyToManyField('Action', related_name='permissions', blank=True, verbose_name=_('Action'))
is_active = models.BooleanField(default=True, verbose_name=_('Active'))
date_start = models.DateTimeField(default=timezone.now, db_index=True, verbose_name=_("Date start"))
date_expired = models.DateTimeField(default=date_expired_default, db_index=True, verbose_name=_('Date expired'))

@ -4,7 +4,7 @@
from rest_framework import serializers
from common.fields import StringManyToManyField
from .models import AssetPermission
from .models import AssetPermission, Action
from assets.models import Node, Asset, SystemUser
from assets.serializers import AssetGrantedSerializer
@ -13,9 +13,16 @@ __all__ = [
'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer',
'AssetPermissionNodeSerializer', 'GrantedNodeSerializer',
'GrantedAssetSerializer', 'GrantedSystemUserSerializer',
'ActionSerializer',
]
class ActionSerializer(serializers.ModelSerializer):
class Meta:
model = Action
fields = '__all__'
class AssetPermissionCreateUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = AssetPermission
@ -28,6 +35,7 @@ class AssetPermissionListSerializer(serializers.ModelSerializer):
assets = StringManyToManyField(many=True, read_only=True)
nodes = StringManyToManyField(many=True, read_only=True)
system_users = StringManyToManyField(many=True, read_only=True)
actions = StringManyToManyField(many=True, read_only=True)
is_valid = serializers.BooleanField()
is_expired = serializers.BooleanField()

@ -2,15 +2,37 @@
#
from django.db.models.signals import m2m_changed, post_save, post_delete
from django.dispatch import receiver
from django.db import transaction
from common.utils import get_logger
from .utils import AssetPermissionUtil
from .models import AssetPermission
from .models import AssetPermission, Action
logger = get_logger(__file__)
def on_transaction_commit(func):
"""
如果不调用on_commit, 对象创建时添加多对多字段值失败
"""
def inner(*args, **kwargs):
transaction.on_commit(lambda: func(*args, **kwargs))
return inner
@receiver(post_save, sender=AssetPermission, dispatch_uid="my_unique_identifier")
@on_transaction_commit
def on_permission_created(sender, instance=None, created=False, **kwargs):
actions = instance.actions.all()
if created and not actions:
default_action = Action.get_action_all()
instance.actions.add(default_action)
logger.debug(
"Set default action to perms: {}".format(default_action, instance)
)
@receiver(post_save, sender=AssetPermission)
def on_permission_update(sender, **kwargs):
AssetPermissionUtil.expire_all_cache()

@ -47,6 +47,9 @@
{% bootstrap_field form.nodes layout="horizontal" %}
{% bootstrap_field form.system_users layout="horizontal" %}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Action' %}</h3>
{% bootstrap_field form.actions layout="horizontal" %}
<div class="hr-line-dashed"></div>
<h3>{% trans 'Other' %}</h3>
<div class="form-group">
<label for="{{ form.is_active.id_for_label }}" class="col-sm-2 control-label">{% trans 'Active' %}</label>

@ -7,6 +7,7 @@ from .. import api
app_name = 'perms'
router = routers.DefaultRouter()
router.register('actions', api.ActionViewSet, 'action')
router.register('asset-permissions', api.AssetPermissionViewSet, 'asset-permission')
urlpatterns = [
@ -67,6 +68,8 @@ urlpatterns = [
# 验证用户是否有某个资产和系统用户的权限
path('asset-permission/user/validate/', api.ValidateUserAssetPermissionApi.as_view(),
name='validate-user-asset-permission'),
path('asset-permission/user/actions/', api.GetUserAssetPermissionActionsApi.as_view(),
name='get-user-asset-permission-actions'),
]
urlpatterns += router.urls

@ -1,6 +1,5 @@
# coding: utf-8
from __future__ import absolute_import, unicode_literals
import uuid
from collections import defaultdict
import json
@ -13,7 +12,7 @@ from django.conf import settings
from common.utils import get_logger
from common.tree import TreeNode
from .models import AssetPermission
from .models import AssetPermission, Action
from .hands import Node
logger = get_logger(__file__)
@ -101,7 +100,7 @@ class AssetPermissionUtil:
"UserGroup": get_user_group_permissions,
"Asset": get_asset_permissions,
"Node": get_node_permissions,
"SystemUser": get_node_permissions,
"SystemUser": get_system_user_permissions,
}
CACHE_KEY_PREFIX = '_ASSET_PERM_CACHE_'
@ -180,6 +179,24 @@ class AssetPermissionUtil:
)
return assets
def _setattr_actions_to_system_user(self):
"""
动态给system_use设置属性actions
"""
for asset, system_users in self._assets.items():
# 获取资产和资产的祖先节点的所有授权规则
perms = get_asset_permissions(asset, include_node=True)
# 过滤当前self.permission的授权规则
perms = perms.filter(id__in=[perm.id for perm in self.permissions])
for system_user in system_users:
actions = set()
_perms = perms.filter(system_users=system_user).\
prefetch_related('actions')
for _perm in _perms:
actions.update(_perm.actions.all())
setattr(system_user, 'actions', actions)
def get_assets_without_cache(self):
if self._assets:
return self._assets
@ -192,6 +209,7 @@ class AssetPermissionUtil:
[s for s in system_users if s.protocol == asset.protocol]
)
self._assets = assets
self._setattr_actions_to_system_user()
return self._assets
def get_cache_key(self, resource):
@ -395,6 +413,7 @@ def parse_asset_to_tree_node(node, asset, system_users):
'protocol': system_user.protocol,
'priority': system_user.priority,
'login_mode': system_user.login_mode,
'actions': [action.name for action in system_user.actions],
'comment': system_user.comment,
})
data = {
@ -423,3 +442,21 @@ def parse_asset_to_tree_node(node, asset, system_users):
}
tree_node = TreeNode(**data)
return tree_node
#
# actions
#
def check_system_user_action(system_user, action):
"""
:param system_user: SystemUser object (包含动态属性: actions)
:param action: Action object
:return: bool
"""
check_actions = [Action.get_action_all(), action]
granted_actions = getattr(system_user, 'actions', [])
actions = list(set(granted_actions).intersection(set(check_actions)))
return bool(actions)

@ -11,8 +11,9 @@ from django.conf import settings
from common.permissions import AdminUserRequiredMixin
from orgs.utils import current_org
from .hands import Node, Asset, SystemUser, User, UserGroup
from .models import AssetPermission
from .models import AssetPermission, Action
from .forms import AssetPermissionForm
from .const import PERMS_ACTION_NAME_ALL
class AssetPermissionListView(AdminUserRequiredMixin, TemplateView):
@ -46,6 +47,8 @@ class AssetPermissionCreateView(AdminUserRequiredMixin, CreateView):
assets_id = assets_id.split(",")
assets = Asset.objects.filter(id__in=assets_id)
form['assets'].initial = assets
form['actions'].initial = Action.objects.get(name=PERMS_ACTION_NAME_ALL)
return form
def get_context_data(self, **kwargs):

Loading…
Cancel
Save