From f235e2015365634dba93e7800d7614710da6e411 Mon Sep 17 00:00:00 2001 From: BaiJiangJie <32935519+BaiJiangJie@users.noreply.github.com> Date: Mon, 22 Apr 2019 11:42:20 +0800 Subject: [PATCH] =?UTF-8?q?[Feature]=20=E6=8E=88=E6=9D=83=E8=A7=84?= =?UTF-8?q?=E5=88=99=E6=B7=BB=E5=8A=A0=20actions=20=E9=80=89=E9=A1=B9?= =?UTF-8?q?=EF=BC=8C=E6=8E=A7=E5=88=B6=E7=94=A8=E6=88=B7=E5=AF=B9=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E7=9A=84=E6=93=8D=E4=BD=9C=E8=A1=8C=E4=B8=BA=20(#2610?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [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 - 添加翻译信息 --- apps/assets/serializers/system_user.py | 8 +- apps/locale/zh/LC_MESSAGES/django.mo | Bin 70722 -> 71390 bytes apps/locale/zh/LC_MESSAGES/django.po | 141 +++++++++++------- apps/perms/api/permission.py | 10 +- apps/perms/api/user_permission.py | 45 +++++- apps/perms/const.py | 22 +++ apps/perms/forms.py | 7 + apps/perms/migrations/0003_action.py | 33 ++++ .../0004_assetpermission_actions.py | 31 ++++ apps/perms/models.py | 21 +++ apps/perms/serializers.py | 10 +- apps/perms/signals_handler.py | 24 ++- .../perms/asset_permission_create_update.html | 3 + apps/perms/urls/api_urls.py | 3 + apps/perms/utils.py | 43 +++++- apps/perms/views.py | 5 +- 16 files changed, 332 insertions(+), 74 deletions(-) create mode 100644 apps/perms/const.py create mode 100644 apps/perms/migrations/0003_action.py create mode 100644 apps/perms/migrations/0004_assetpermission_actions.py diff --git a/apps/assets/serializers/system_user.py b/apps/assets/serializers/system_user.py index be1f594ec..b4387d1ff 100644 --- a/apps/assets/serializers/system_user.py +++ b/apps/assets/serializers/system_user.py @@ -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): """ diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index ddf7a8865876add6ab6f0e0c3c0adea06eedb89b..4bd12ed4a8ebc044210540bca16a4f21c73ee012 100644 GIT binary patch delta 21453 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 delta 20791 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 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 776273e3f..561e31db9 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -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 \n" "Language-Team: Jumpserver team\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 "同步用户" diff --git a/apps/perms/api/permission.py b/apps/perms/api/permission.py index c425c90ad..a0381e698 100644 --- a/apps/perms/api/permission.py +++ b/apps/perms/api/permission.py @@ -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 diff --git a/apps/perms/api/user_permission.py b/apps/perms/api/user_permission.py index ecb3b4c3d..8d1a42c26 100644 --- a/apps/perms/api/user_permission.py +++ b/apps/perms/api/user_permission.py @@ -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) diff --git a/apps/perms/const.py b/apps/perms/const.py new file mode 100644 index 000000000..4dc315c06 --- /dev/null +++ b/apps/perms/const.py @@ -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')), +) diff --git a/apps/perms/forms.py b/apps/perms/forms.py index a07cdb2ef..35d8a2528 100644 --- a/apps/perms/forms.py +++ b/apps/perms/forms.py @@ -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') diff --git a/apps/perms/migrations/0003_action.py b/apps/perms/migrations/0003_action.py new file mode 100644 index 000000000..41c0f9f39 --- /dev/null +++ b/apps/perms/migrations/0003_action.py @@ -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) + ] diff --git a/apps/perms/migrations/0004_assetpermission_actions.py b/apps/perms/migrations/0004_assetpermission_actions.py new file mode 100644 index 000000000..be468e7f0 --- /dev/null +++ b/apps/perms/migrations/0004_assetpermission_actions.py @@ -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) + ] diff --git a/apps/perms/models.py b/apps/perms/models.py index 1ae4f5e69..c524c4f58 100644 --- a/apps/perms/models.py +++ b/apps/perms/models.py @@ -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')) diff --git a/apps/perms/serializers.py b/apps/perms/serializers.py index cd874ce1f..01c5a077a 100644 --- a/apps/perms/serializers.py +++ b/apps/perms/serializers.py @@ -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() diff --git a/apps/perms/signals_handler.py b/apps/perms/signals_handler.py index 7876d7642..97884db1b 100644 --- a/apps/perms/signals_handler.py +++ b/apps/perms/signals_handler.py @@ -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() diff --git a/apps/perms/templates/perms/asset_permission_create_update.html b/apps/perms/templates/perms/asset_permission_create_update.html index b6789abbf..cf7a46eff 100644 --- a/apps/perms/templates/perms/asset_permission_create_update.html +++ b/apps/perms/templates/perms/asset_permission_create_update.html @@ -47,6 +47,9 @@ {% bootstrap_field form.nodes layout="horizontal" %} {% bootstrap_field form.system_users layout="horizontal" %}
+

{% trans 'Action' %}

+ {% bootstrap_field form.actions layout="horizontal" %} +

{% trans 'Other' %}

diff --git a/apps/perms/urls/api_urls.py b/apps/perms/urls/api_urls.py index 00e842f52..5894d3835 100644 --- a/apps/perms/urls/api_urls.py +++ b/apps/perms/urls/api_urls.py @@ -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 diff --git a/apps/perms/utils.py b/apps/perms/utils.py index 4243b17bd..bd5094def 100644 --- a/apps/perms/utils.py +++ b/apps/perms/utils.py @@ -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) diff --git a/apps/perms/views.py b/apps/perms/views.py index 6b0a0d5d3..0e02b38a7 100644 --- a/apps/perms/views.py +++ b/apps/perms/views.py @@ -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):