mirror of https://github.com/jumpserver/jumpserver
perf: 批量上传添加权限校验
parent
0aeea414f5
commit
9776d35140
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:0bd11124a56e5fa0b2b8433528d4ffd8c454e5f529bdd72fea15d1a62434165e
|
||||
size 176114
|
||||
oid sha256:488d95a4a96d38c3c0633f183334498d9e247bdf66ce3a4bcc836f80e8320432
|
||||
size 176705
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-03 16:51+0800\n"
|
||||
"POT-Creation-Date: 2024-04-07 14:23+0800\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -1362,13 +1362,13 @@ msgstr "アプリケーション"
|
|||
msgid "Can match application"
|
||||
msgstr "アプリケーションを一致させることができます"
|
||||
|
||||
#: assets/api/asset/asset.py:181
|
||||
#: assets/api/asset/asset.py:180
|
||||
msgid "Cannot create asset directly, you should create a host or other"
|
||||
msgstr ""
|
||||
"資産を直接作成することはできません。ホストまたはその他を作成する必要がありま"
|
||||
"す"
|
||||
|
||||
#: assets/api/domain.py:68
|
||||
#: assets/api/domain.py:67
|
||||
msgid "Number required"
|
||||
msgstr "必要な数"
|
||||
|
||||
|
@ -4137,11 +4137,24 @@ msgstr "タスクは存在しません"
|
|||
msgid "Task {} args or kwargs error"
|
||||
msgstr "タスク実行パラメータエラー"
|
||||
|
||||
#: ops/api/job.py:146
|
||||
msgid ""
|
||||
"Asset ({asset}) must have at least one of the following protocols added: "
|
||||
"SSH, SFTP, or WinRM"
|
||||
msgstr ""
|
||||
"資産({asset})には、少なくともSSH、SFTP、WinRMのいずれか一つのプロトコルを追加す"
|
||||
"る必要があります"
|
||||
|
||||
msgid "Asset ({asset}) authorization is missing SSH, SFTP, or WinRM protocol"
|
||||
msgstr "資産({asset})の認証にはSSH、SFTP、またはWinRMプロトコルが不足しています"
|
||||
|
||||
msgid "Asset ({asset}) authorization lacks upload permissions"
|
||||
msgstr "資産({asset})の認証にはアップロード権限が不足しています"
|
||||
|
||||
#: ops/api/job.py:168
|
||||
msgid "Duplicate file exists"
|
||||
msgstr "重複したファイルが存在する"
|
||||
|
||||
#: ops/api/job.py:151
|
||||
#: ops/api/job.py:173
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"File size exceeds maximum limit. Please select a file smaller than {limit}MB"
|
||||
|
@ -4149,7 +4162,7 @@ msgstr ""
|
|||
"ファイルサイズが最大制限を超えています。{limit}MB より小さいファイルを選択し"
|
||||
"てください。"
|
||||
|
||||
#: ops/api/job.py:215
|
||||
#: ops/api/job.py:237
|
||||
msgid ""
|
||||
"The task is being created and cannot be interrupted. Please try again later."
|
||||
msgstr "タスクを作成中で、中断できません。後でもう一度お試しください。"
|
||||
|
@ -4537,18 +4550,18 @@ msgstr "ジョブのID"
|
|||
msgid "Name of the job"
|
||||
msgstr "ジョブの名前"
|
||||
|
||||
#: orgs/api.py:62
|
||||
#: orgs/api.py:61
|
||||
msgid "The current organization ({}) cannot be deleted"
|
||||
msgstr "現在の組織 ({}) は削除できません"
|
||||
|
||||
#: orgs/api.py:67
|
||||
#: orgs/api.py:66
|
||||
msgid ""
|
||||
"LDAP synchronization is set to the current organization. Please switch to "
|
||||
"another organization before deleting"
|
||||
msgstr ""
|
||||
"LDAP 同期は現在の組織に設定されます。削除する前に別の組織に切り替えてください"
|
||||
|
||||
#: orgs/api.py:77
|
||||
#: orgs/api.py:76
|
||||
msgid "The organization have resource ({}) cannot be deleted"
|
||||
msgstr "組織のリソース ({}) は削除できません"
|
||||
|
||||
|
@ -6531,11 +6544,11 @@ msgstr "これはエンタープライズ版アプレットです"
|
|||
msgid "Not found protocol query params"
|
||||
msgstr "プロトコルクエリパラメータが見つかりません"
|
||||
|
||||
#: terminal/api/component/storage.py:30
|
||||
#: terminal/api/component/storage.py:31
|
||||
msgid "Deleting the default storage is not allowed"
|
||||
msgstr "デフォルトのストレージの削除は許可されていません"
|
||||
|
||||
#: terminal/api/component/storage.py:33
|
||||
#: terminal/api/component/storage.py:34
|
||||
msgid "Cannot delete storage that is being used"
|
||||
msgstr "使用中のストレージを削除できません"
|
||||
|
||||
|
@ -6547,15 +6560,15 @@ msgstr "コマンドストア"
|
|||
msgid "Invalid"
|
||||
msgstr "無効"
|
||||
|
||||
#: terminal/api/component/storage.py:131 terminal/tasks.py:149
|
||||
#: terminal/api/component/storage.py:130 terminal/tasks.py:149
|
||||
msgid "Test failure: {}"
|
||||
msgstr "テスト失敗: {}"
|
||||
|
||||
#: terminal/api/component/storage.py:134
|
||||
#: terminal/api/component/storage.py:133
|
||||
msgid "Test successful"
|
||||
msgstr "テスト成功"
|
||||
|
||||
#: terminal/api/component/storage.py:136
|
||||
#: terminal/api/component/storage.py:135
|
||||
msgid "Test failure: Please check configuration"
|
||||
msgstr "テストに失敗しました:構成を確認してください"
|
||||
|
||||
|
@ -7890,11 +7903,11 @@ msgstr "無効な承認アクション"
|
|||
msgid "This user is not authorized to approve this ticket"
|
||||
msgstr "このユーザーはこの作業指示を承認する権限がありません"
|
||||
|
||||
#: users/api/user.py:137
|
||||
#: users/api/user.py:136
|
||||
msgid "Can not invite self"
|
||||
msgstr "自分自身を招待することはできません"
|
||||
|
||||
#: users/api/user.py:190
|
||||
#: users/api/user.py:189
|
||||
msgid "Could not reset self otp, use profile reset instead"
|
||||
msgstr "自己otpをリセットできませんでした、代わりにプロファイルリセットを使用"
|
||||
|
||||
|
@ -9311,6 +9324,3 @@ msgstr "エンタープライズプロフェッショナル版"
|
|||
#: xpack/plugins/license/models.py:86
|
||||
msgid "Ultimate edition"
|
||||
msgstr "エンタープライズ・フラッグシップ・エディション"
|
||||
|
||||
#~ msgid "Reopen"
|
||||
#~ msgstr "再オープン"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:91ad10be95fda19937a09d07806d05f21057a1a79f40428350127d1162c7655d
|
||||
size 144168
|
||||
oid sha256:bd99d1b6018567413cefe5fe188a19019e09da46934c05ae9ce229943f712859
|
||||
size 144595
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-04-03 16:51+0800\n"
|
||||
"POT-Creation-Date: 2024-04-07 14:23+0800\n"
|
||||
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
||||
|
@ -1354,11 +1354,11 @@ msgstr "应用程序"
|
|||
msgid "Can match application"
|
||||
msgstr "匹配应用"
|
||||
|
||||
#: assets/api/asset/asset.py:181
|
||||
#: assets/api/asset/asset.py:180
|
||||
msgid "Cannot create asset directly, you should create a host or other"
|
||||
msgstr "不能直接创建资产, 你应该创建主机或其他资产"
|
||||
|
||||
#: assets/api/domain.py:68
|
||||
#: assets/api/domain.py:67
|
||||
msgid "Number required"
|
||||
msgstr "需要为数字"
|
||||
|
||||
|
@ -4086,17 +4086,28 @@ msgstr "任务 {} 不存在"
|
|||
msgid "Task {} args or kwargs error"
|
||||
msgstr "任务 {} 执行参数错误"
|
||||
|
||||
#: ops/api/job.py:146
|
||||
msgid ""
|
||||
"Asset ({asset}) must have at least one of the following protocols added: "
|
||||
"SSH, SFTP, or WinRM"
|
||||
msgstr "资产({asset})至少要添加ssh,sftp,winrm其中一种协议"
|
||||
|
||||
msgid "Asset ({asset}) authorization is missing SSH, SFTP, or WinRM protocol"
|
||||
msgstr "资产({asset})授权缺少ssh,sftp或winrm协议"
|
||||
|
||||
msgid "Asset ({asset}) authorization lacks upload permissions"
|
||||
msgstr "资产({asset})授权缺少上传权限"
|
||||
|
||||
#: ops/api/job.py:168
|
||||
msgid "Duplicate file exists"
|
||||
msgstr "存在同名文件"
|
||||
|
||||
#: ops/api/job.py:151
|
||||
#: ops/api/job.py:173
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"File size exceeds maximum limit. Please select a file smaller than {limit}MB"
|
||||
msgstr "文件大小超过最大限制。请选择小于 {limit}MB 的文件。"
|
||||
|
||||
#: ops/api/job.py:215
|
||||
#: ops/api/job.py:237
|
||||
msgid ""
|
||||
"The task is being created and cannot be interrupted. Please try again later."
|
||||
msgstr "正在创建任务,无法中断,请稍后重试。"
|
||||
|
@ -4484,17 +4495,17 @@ msgstr "Job ID"
|
|||
msgid "Name of the job"
|
||||
msgstr "Job 名称"
|
||||
|
||||
#: orgs/api.py:62
|
||||
#: orgs/api.py:61
|
||||
msgid "The current organization ({}) cannot be deleted"
|
||||
msgstr "当前组织 ({}) 不能被删除"
|
||||
|
||||
#: orgs/api.py:67
|
||||
#: orgs/api.py:66
|
||||
msgid ""
|
||||
"LDAP synchronization is set to the current organization. Please switch to "
|
||||
"another organization before deleting"
|
||||
msgstr "LDAP 同步设置组织为当前组织,请切换其他组织后再进行删除操作"
|
||||
|
||||
#: orgs/api.py:77
|
||||
#: orgs/api.py:76
|
||||
msgid "The organization have resource ({}) cannot be deleted"
|
||||
msgstr "组织存在资源 ({}) 不能被删除"
|
||||
|
||||
|
@ -6435,11 +6446,11 @@ msgstr "企业版远程应用,在社区版中不能使用"
|
|||
msgid "Not found protocol query params"
|
||||
msgstr "未发现 protocol 查询参数"
|
||||
|
||||
#: terminal/api/component/storage.py:30
|
||||
#: terminal/api/component/storage.py:31
|
||||
msgid "Deleting the default storage is not allowed"
|
||||
msgstr "不允许删除默认存储配置"
|
||||
|
||||
#: terminal/api/component/storage.py:33
|
||||
#: terminal/api/component/storage.py:34
|
||||
msgid "Cannot delete storage that is being used"
|
||||
msgstr "不允许删除正在使用的存储配置"
|
||||
|
||||
|
@ -6451,15 +6462,15 @@ msgstr "命令存储"
|
|||
msgid "Invalid"
|
||||
msgstr "无效"
|
||||
|
||||
#: terminal/api/component/storage.py:131 terminal/tasks.py:149
|
||||
#: terminal/api/component/storage.py:130 terminal/tasks.py:149
|
||||
msgid "Test failure: {}"
|
||||
msgstr "测试失败: {}"
|
||||
|
||||
#: terminal/api/component/storage.py:134
|
||||
#: terminal/api/component/storage.py:133
|
||||
msgid "Test successful"
|
||||
msgstr "测试成功"
|
||||
|
||||
#: terminal/api/component/storage.py:136
|
||||
#: terminal/api/component/storage.py:135
|
||||
msgid "Test failure: Please check configuration"
|
||||
msgstr "测试失败:请检查配置"
|
||||
|
||||
|
@ -7781,11 +7792,11 @@ msgstr "无效的审批动作"
|
|||
msgid "This user is not authorized to approve this ticket"
|
||||
msgstr "此用户无权审批此工单"
|
||||
|
||||
#: users/api/user.py:137
|
||||
#: users/api/user.py:136
|
||||
msgid "Can not invite self"
|
||||
msgstr "不能邀请自己"
|
||||
|
||||
#: users/api/user.py:190
|
||||
#: users/api/user.py:189
|
||||
msgid "Could not reset self otp, use profile reset instead"
|
||||
msgstr "不能在该页面重置 MFA 多因子认证, 请去个人信息页面重置"
|
||||
|
||||
|
@ -9182,6 +9193,3 @@ msgstr "企业专业版"
|
|||
#: xpack/plugins/license/models.py:86
|
||||
msgid "Ultimate edition"
|
||||
msgstr "企业旗舰版"
|
||||
|
||||
#~ msgid "Reopen"
|
||||
#~ msgstr "重新打开"
|
||||
|
|
|
@ -32,6 +32,9 @@ from ops.variables import JMS_JOB_VARIABLE_HELP
|
|||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from orgs.utils import tmp_to_org, get_current_org
|
||||
from accounts.models import Account
|
||||
from assets.const import Protocol
|
||||
from perms.const import ActionChoices
|
||||
from perms.utils.asset_perm import PermAssetDetailUtil
|
||||
from perms.models import PermNode
|
||||
from perms.utils import UserPermAssetUtil
|
||||
from jumpserver.settings import get_file_md5
|
||||
|
@ -72,6 +75,22 @@ class JobViewSet(OrgBulkModelViewSet):
|
|||
return self.permission_denied(request, "Command execution disabled")
|
||||
return super().check_permissions(request)
|
||||
|
||||
def check_upload_permission(self, assets, account_name):
|
||||
protocols_required = {Protocol.ssh, Protocol.sftp, Protocol.winrm}
|
||||
error_msg_missing_protocol = _(
|
||||
"Asset ({asset}) must have at least one of the following protocols added: SSH, SFTP, or WinRM")
|
||||
error_msg_auth_missing_protocol = _("Asset ({asset}) authorization is missing SSH, SFTP, or WinRM protocol")
|
||||
error_msg_auth_missing_upload = _("Asset ({asset}) authorization lacks upload permissions")
|
||||
for asset in assets:
|
||||
protocols = asset.protocols.values_list("name", flat=True)
|
||||
if not set(protocols).intersection(protocols_required):
|
||||
self.permission_denied(self.request, error_msg_missing_protocol.format(asset=asset.name))
|
||||
util = PermAssetDetailUtil(self.request.user, asset)
|
||||
if not util.check_perm_protocols(protocols_required):
|
||||
self.permission_denied(self.request, error_msg_auth_missing_protocol.format(asset=asset.name))
|
||||
if not util.check_perm_actions(account_name, [ActionChoices.upload.value]):
|
||||
self.permission_denied(self.request, error_msg_auth_missing_upload.format(asset=asset.name))
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset \
|
||||
|
@ -89,6 +108,9 @@ class JobViewSet(OrgBulkModelViewSet):
|
|||
assets = serializer.validated_data.get('assets')
|
||||
assets = merge_nodes_and_assets(node_ids, assets, self.request.user)
|
||||
serializer.validated_data['assets'] = assets
|
||||
if serializer.validated_data.get('type') == Types.upload_file:
|
||||
account_name = serializer.validated_data.get('runas')
|
||||
self.check_upload_permission(assets, account_name)
|
||||
instance = serializer.save()
|
||||
|
||||
if instance.instant or run_after_save:
|
||||
|
|
|
@ -42,6 +42,10 @@ class ActionChoices(BitChoices):
|
|||
def contains(cls, total, action_value):
|
||||
return action_value & total == action_value
|
||||
|
||||
@classmethod
|
||||
def contains_all(cls, total, action_values):
|
||||
return all(cls.contains(total, action) for action in action_values)
|
||||
|
||||
@classmethod
|
||||
def display(cls, value):
|
||||
return ', '.join([str(c.label) for c in cls if c.value & value == c.value])
|
||||
|
|
|
@ -6,6 +6,7 @@ from assets.models import Asset
|
|||
from common.utils import lazyproperty
|
||||
from orgs.utils import tmp_to_org, tmp_to_root_org
|
||||
from .permission import AssetPermissionUtil
|
||||
from perms.const import ActionChoices
|
||||
|
||||
__all__ = ['PermAssetDetailUtil']
|
||||
|
||||
|
@ -137,3 +138,23 @@ class PermAssetDetailUtil:
|
|||
account.date_expired = max(cleaned_accounts_expired[account])
|
||||
accounts.append(account)
|
||||
return accounts
|
||||
|
||||
def check_perm_protocols(self, protocols):
|
||||
"""
|
||||
检查用户是否有某些协议权限
|
||||
:param protocols: set
|
||||
"""
|
||||
perms_protocols = self.get_permed_protocols_for_user(only_name=True)
|
||||
if "all" in perms_protocols:
|
||||
return True
|
||||
return protocols.intersection(perms_protocols)
|
||||
|
||||
def check_perm_actions(self, account_name, actions):
|
||||
"""
|
||||
检查用户是否有某个账号的某个资产操作权限
|
||||
:param account_name: str
|
||||
:param actions: list
|
||||
"""
|
||||
perms = self.user_asset_perms
|
||||
action_bit_mapper, __ = self.parse_alias_action_date_expire(perms, self.asset)
|
||||
return ActionChoices.contains_all(action_bit_mapper.get(account_name, 0), actions)
|
||||
|
|
Loading…
Reference in New Issue