mirror of https://github.com/jumpserver/jumpserver
feat: 支持批量发送文件
parent
e3ac26e377
commit
d0b0c87d3c
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:5d443763c06877304dca8dac76131271287acc6594df665bdf9445455c5187f1
|
||||
size 167791
|
||||
oid sha256:a00c0d53df7fa88fc2fe69adda31fd9ab581b5a0362a01b8191924f74fab800d
|
||||
size 167820
|
||||
|
|
|
@ -8,8 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-12-08 14:51+0800\n"
|
||||
"POT-Creation-Date: 2023-12-08 15:33+0800\n"
|
||||
"POT-Creation-Date: 2023-12-11 14:54+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"
|
||||
|
@ -88,7 +87,7 @@ msgstr "集めました"
|
|||
msgid "Template"
|
||||
msgstr "テンプレート"
|
||||
|
||||
#: accounts/const/account.py:31 ops/const.py:45
|
||||
#: accounts/const/account.py:31 ops/const.py:46
|
||||
msgid "Skip"
|
||||
msgstr "スキップ"
|
||||
|
||||
|
@ -100,7 +99,7 @@ msgstr "更新"
|
|||
#: accounts/const/account.py:33
|
||||
#: accounts/serializers/automations/change_secret.py:150 audits/const.py:62
|
||||
#: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19
|
||||
#: ops/const.py:74 terminal/const.py:79 xpack/plugins/cloud/const.py:46
|
||||
#: ops/const.py:75 terminal/const.py:79 xpack/plugins/cloud/const.py:46
|
||||
msgid "Failed"
|
||||
msgstr "失敗しました"
|
||||
|
||||
|
@ -208,7 +207,6 @@ msgstr "作成のみ"
|
|||
msgid "Email"
|
||||
msgstr "メール"
|
||||
|
||||
#: accounts/const/automation.py:104 terminal/const.py:87
|
||||
#: accounts/const/automation.py:105 terminal/const.py:87
|
||||
msgid "SFTP"
|
||||
msgstr "SFTP"
|
||||
|
@ -265,7 +263,7 @@ msgstr "資産"
|
|||
#: accounts/models/account.py:53 accounts/models/template.py:16
|
||||
#: accounts/serializers/account/account.py:220
|
||||
#: accounts/serializers/account/account.py:268
|
||||
#: accounts/serializers/account/template.py:25
|
||||
#: accounts/serializers/account/template.py:27
|
||||
#: authentication/serializers/connect_token_secret.py:50
|
||||
msgid "Su from"
|
||||
msgstr "から切り替え"
|
||||
|
@ -397,7 +395,7 @@ msgstr "理由"
|
|||
#: accounts/models/automations/backup_account.py:135
|
||||
#: accounts/serializers/automations/change_secret.py:105
|
||||
#: accounts/serializers/automations/change_secret.py:128
|
||||
#: ops/serializers/job.py:55 terminal/serializers/session.py:49
|
||||
#: ops/serializers/job.py:65 terminal/serializers/session.py:49
|
||||
msgid "Is success"
|
||||
msgstr "成功は"
|
||||
|
||||
|
@ -585,7 +583,7 @@ msgstr "ひみつ"
|
|||
msgid "Secret strategy"
|
||||
msgstr "鍵ポリシー"
|
||||
|
||||
#: accounts/models/base.py:44 accounts/serializers/account/template.py:22
|
||||
#: accounts/models/base.py:44 accounts/serializers/account/template.py:24
|
||||
#: accounts/serializers/automations/change_secret.py:44
|
||||
msgid "Password rules"
|
||||
msgstr "パスワードルール"
|
||||
|
@ -902,19 +900,19 @@ msgstr "数値#スウスウ#"
|
|||
msgid "Special symbol"
|
||||
msgstr "特殊記号"
|
||||
|
||||
#: accounts/serializers/account/template.py:18
|
||||
#: accounts/serializers/account/template.py:19
|
||||
msgid "Exclude symbol"
|
||||
msgstr "除外文字"
|
||||
|
||||
#: accounts/serializers/account/template.py:36
|
||||
#: accounts/serializers/account/template.py:38
|
||||
msgid "Secret generation strategy for account creation"
|
||||
msgstr "账号创建时,密文生成策略"
|
||||
|
||||
#: accounts/serializers/account/template.py:37
|
||||
#: accounts/serializers/account/template.py:39
|
||||
msgid "Whether to automatically push the account to the asset"
|
||||
msgstr "是否自动推送账号到资产"
|
||||
|
||||
#: accounts/serializers/account/template.py:40
|
||||
#: accounts/serializers/account/template.py:42
|
||||
msgid ""
|
||||
"Associated platform, you can configure push parameters. If not associated, "
|
||||
"default parameters will be used"
|
||||
|
@ -980,7 +978,7 @@ msgstr "自動タスク実行履歴"
|
|||
|
||||
#: accounts/serializers/automations/change_secret.py:149 audits/const.py:61
|
||||
#: audits/models.py:64 audits/signal_handlers/activity_log.py:33
|
||||
#: common/const/choices.py:18 ops/const.py:72 ops/serializers/celery.py:40
|
||||
#: common/const/choices.py:18 ops/const.py:73 ops/serializers/celery.py:40
|
||||
#: terminal/const.py:78 terminal/models/session/sharing.py:121
|
||||
#: tickets/views/approve.py:117
|
||||
msgid "Success"
|
||||
|
@ -1118,7 +1116,7 @@ msgid "Accounts"
|
|||
msgstr "アカウント"
|
||||
|
||||
#: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60
|
||||
#: ops/serializers/job.py:54 terminal/const.py:86
|
||||
#: ops/serializers/job.py:64 terminal/const.py:86
|
||||
#: terminal/models/session/session.py:42 terminal/serializers/command.py:18
|
||||
#: terminal/templates/terminal/_msg_command_alert.html:12
|
||||
#: terminal/templates/terminal/_msg_command_execute_alert.html:10
|
||||
|
@ -1668,7 +1666,7 @@ msgstr "プロトコル"
|
|||
msgid "Sudo"
|
||||
msgstr "すど"
|
||||
|
||||
#: assets/models/_user.py:55 ops/const.py:49 ops/const.py:59
|
||||
#: assets/models/_user.py:55 ops/const.py:50 ops/const.py:60
|
||||
msgid "Shell"
|
||||
msgstr "シェル"
|
||||
|
||||
|
@ -3639,7 +3637,7 @@ msgstr "の準備を"
|
|||
msgid "Pending"
|
||||
msgstr "未定"
|
||||
|
||||
#: common/const/choices.py:17 ops/const.py:71
|
||||
#: common/const/choices.py:17 ops/const.py:72
|
||||
msgid "Running"
|
||||
msgstr "ランニング"
|
||||
|
||||
|
@ -4053,6 +4051,10 @@ msgstr "タスクは存在しません"
|
|||
msgid "Task {} args or kwargs error"
|
||||
msgstr "タスク実行パラメータエラー"
|
||||
|
||||
#: ops/api/job.py:128
|
||||
msgid "Duplicate file exists"
|
||||
msgstr "重複したファイルが存在する"
|
||||
|
||||
#: ops/api/playbook.py:39
|
||||
msgid "Currently playbook is being used in a job"
|
||||
msgstr "現在プレイブックは1つのジョブで使用されています"
|
||||
|
@ -4125,47 +4127,53 @@ msgstr "コマンド#コマンド#"
|
|||
msgid "Playbook"
|
||||
msgstr "Playbook"
|
||||
|
||||
#: ops/const.py:43
|
||||
#: ops/const.py:40
|
||||
#, fuzzy
|
||||
#| msgid "Upload"
|
||||
msgid "Upload File"
|
||||
msgstr "アップロード"
|
||||
|
||||
#: ops/const.py:44
|
||||
msgid "Privileged Only"
|
||||
msgstr "特権アカウントのみ"
|
||||
|
||||
#: ops/const.py:44
|
||||
#: ops/const.py:45
|
||||
msgid "Privileged First"
|
||||
msgstr "特権アカウント優先"
|
||||
|
||||
#: ops/const.py:50 ops/const.py:60
|
||||
#: ops/const.py:51 ops/const.py:61
|
||||
msgid "Powershell"
|
||||
msgstr "PowerShell"
|
||||
|
||||
#: ops/const.py:51 ops/const.py:61
|
||||
#: ops/const.py:52 ops/const.py:62
|
||||
msgid "Python"
|
||||
msgstr "Python"
|
||||
|
||||
#: ops/const.py:52 ops/const.py:62
|
||||
#: ops/const.py:53 ops/const.py:63
|
||||
msgid "MySQL"
|
||||
msgstr "MySQL"
|
||||
|
||||
#: ops/const.py:53 ops/const.py:64
|
||||
#: ops/const.py:54 ops/const.py:65
|
||||
msgid "PostgreSQL"
|
||||
msgstr "PostgreSQL"
|
||||
|
||||
#: ops/const.py:54 ops/const.py:65
|
||||
#: ops/const.py:55 ops/const.py:66
|
||||
msgid "SQLServer"
|
||||
msgstr "SQLServer"
|
||||
|
||||
#: ops/const.py:55 ops/const.py:67
|
||||
#: ops/const.py:56 ops/const.py:68
|
||||
msgid "Raw"
|
||||
msgstr ""
|
||||
|
||||
#: ops/const.py:63
|
||||
#: ops/const.py:64
|
||||
msgid "MariaDB"
|
||||
msgstr "MariaDB"
|
||||
|
||||
#: ops/const.py:66
|
||||
#: ops/const.py:67
|
||||
msgid "Oracle"
|
||||
msgstr "Oracle"
|
||||
|
||||
#: ops/const.py:73
|
||||
#: ops/const.py:74
|
||||
msgid "Timeout"
|
||||
msgstr "タイムアウト"
|
||||
|
||||
|
@ -4299,7 +4307,7 @@ msgstr "Material"
|
|||
msgid "Material Type"
|
||||
msgstr "Material を選択してオプションを設定します。"
|
||||
|
||||
#: ops/models/job.py:557
|
||||
#: ops/models/job.py:565
|
||||
msgid "Job Execution"
|
||||
msgstr "ジョブ実行"
|
||||
|
||||
|
@ -4343,15 +4351,15 @@ msgstr "{max_threshold} を超えるCPUロード: => {value}"
|
|||
msgid "Run after save"
|
||||
msgstr "保存後に実行"
|
||||
|
||||
#: ops/serializers/job.py:53
|
||||
#: ops/serializers/job.py:63
|
||||
msgid "Job type"
|
||||
msgstr "タスクの種類"
|
||||
|
||||
#: ops/serializers/job.py:56 terminal/serializers/session.py:53
|
||||
#: ops/serializers/job.py:66 terminal/serializers/session.py:53
|
||||
msgid "Is finished"
|
||||
msgstr "終了しました"
|
||||
|
||||
#: ops/serializers/job.py:57
|
||||
#: ops/serializers/job.py:67
|
||||
msgid "Time cost"
|
||||
msgstr "時を過ごす"
|
||||
|
||||
|
@ -4567,7 +4575,8 @@ msgstr "認定アカウント"
|
|||
msgid "today"
|
||||
msgstr "今日"
|
||||
|
||||
#: perms/notifications.py:12 settings/serializers/feature.py:106
|
||||
#: perms/notifications.py:12 perms/notifications.py:44
|
||||
#: settings/serializers/feature.py:106
|
||||
msgid "day"
|
||||
msgstr "日"
|
||||
|
||||
|
@ -4595,8 +4604,9 @@ msgstr "アセット認証ルールの有効期限が切れていることを確
|
|||
msgid "Send asset permission expired notification"
|
||||
msgstr "アセット許可の有効期限通知を送信する"
|
||||
|
||||
|
||||
#: perms/templates/perms/_msg_item_permissions_expire.html:7
|
||||
#: perms/templates/perms/_msg_permed_items_expire.html:7
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" The following %(item_type)s will expire in %(count)s\n"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:8976c6b41e2c0ce591b2b257fd0352b4ed7517661f7df83ba74b302b8cf94b00
|
||||
size 137479
|
||||
oid sha256:d4a9a61bf1b247d3843001737ebfa6d5f8580f2d9c1ae0fc76649ecc535f5d96
|
||||
size 137563
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-12-08 15:33+0800\n"
|
||||
"POT-Creation-Date: 2023-12-11 14:54+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"
|
||||
|
@ -86,7 +86,7 @@ msgstr "收集"
|
|||
msgid "Template"
|
||||
msgstr "模板"
|
||||
|
||||
#: accounts/const/account.py:31 ops/const.py:45
|
||||
#: accounts/const/account.py:31 ops/const.py:46
|
||||
msgid "Skip"
|
||||
msgstr "跳过"
|
||||
|
||||
|
@ -98,7 +98,7 @@ msgstr "更新"
|
|||
#: accounts/const/account.py:33
|
||||
#: accounts/serializers/automations/change_secret.py:150 audits/const.py:62
|
||||
#: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19
|
||||
#: ops/const.py:74 terminal/const.py:79 xpack/plugins/cloud/const.py:46
|
||||
#: ops/const.py:75 terminal/const.py:79 xpack/plugins/cloud/const.py:46
|
||||
msgid "Failed"
|
||||
msgstr "失败"
|
||||
|
||||
|
@ -262,7 +262,7 @@ msgstr "资产"
|
|||
#: accounts/models/account.py:53 accounts/models/template.py:16
|
||||
#: accounts/serializers/account/account.py:220
|
||||
#: accounts/serializers/account/account.py:268
|
||||
#: accounts/serializers/account/template.py:25
|
||||
#: accounts/serializers/account/template.py:27
|
||||
#: authentication/serializers/connect_token_secret.py:50
|
||||
msgid "Su from"
|
||||
msgstr "切换自"
|
||||
|
@ -394,7 +394,7 @@ msgstr "原因"
|
|||
#: accounts/models/automations/backup_account.py:135
|
||||
#: accounts/serializers/automations/change_secret.py:105
|
||||
#: accounts/serializers/automations/change_secret.py:128
|
||||
#: ops/serializers/job.py:55 terminal/serializers/session.py:49
|
||||
#: ops/serializers/job.py:65 terminal/serializers/session.py:49
|
||||
msgid "Is success"
|
||||
msgstr "是否成功"
|
||||
|
||||
|
@ -582,7 +582,7 @@ msgstr "密钥"
|
|||
msgid "Secret strategy"
|
||||
msgstr "密文策略"
|
||||
|
||||
#: accounts/models/base.py:44 accounts/serializers/account/template.py:22
|
||||
#: accounts/models/base.py:44 accounts/serializers/account/template.py:24
|
||||
#: accounts/serializers/automations/change_secret.py:44
|
||||
msgid "Password rules"
|
||||
msgstr "密码规则"
|
||||
|
@ -898,19 +898,19 @@ msgstr "数字"
|
|||
msgid "Special symbol"
|
||||
msgstr "特殊字符"
|
||||
|
||||
#: accounts/serializers/account/template.py:18
|
||||
#: accounts/serializers/account/template.py:19
|
||||
msgid "Exclude symbol"
|
||||
msgstr "排除字符"
|
||||
|
||||
#: accounts/serializers/account/template.py:36
|
||||
#: accounts/serializers/account/template.py:38
|
||||
msgid "Secret generation strategy for account creation"
|
||||
msgstr "密码生成策略,用于账号创建时,设置密码"
|
||||
|
||||
#: accounts/serializers/account/template.py:37
|
||||
#: accounts/serializers/account/template.py:39
|
||||
msgid "Whether to automatically push the account to the asset"
|
||||
msgstr "是否自动推送账号到资产"
|
||||
|
||||
#: accounts/serializers/account/template.py:40
|
||||
#: accounts/serializers/account/template.py:42
|
||||
msgid ""
|
||||
"Associated platform, you can configure push parameters. If not associated, "
|
||||
"default parameters will be used"
|
||||
|
@ -975,7 +975,7 @@ msgstr "自动化任务执行历史"
|
|||
|
||||
#: accounts/serializers/automations/change_secret.py:149 audits/const.py:61
|
||||
#: audits/models.py:64 audits/signal_handlers/activity_log.py:33
|
||||
#: common/const/choices.py:18 ops/const.py:72 ops/serializers/celery.py:40
|
||||
#: common/const/choices.py:18 ops/const.py:73 ops/serializers/celery.py:40
|
||||
#: terminal/const.py:78 terminal/models/session/sharing.py:121
|
||||
#: tickets/views/approve.py:117
|
||||
msgid "Success"
|
||||
|
@ -1113,7 +1113,7 @@ msgid "Accounts"
|
|||
msgstr "账号管理"
|
||||
|
||||
#: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60
|
||||
#: ops/serializers/job.py:54 terminal/const.py:86
|
||||
#: ops/serializers/job.py:64 terminal/const.py:86
|
||||
#: terminal/models/session/session.py:42 terminal/serializers/command.py:18
|
||||
#: terminal/templates/terminal/_msg_command_alert.html:12
|
||||
#: terminal/templates/terminal/_msg_command_execute_alert.html:10
|
||||
|
@ -1659,7 +1659,7 @@ msgstr "协议"
|
|||
msgid "Sudo"
|
||||
msgstr "Sudo"
|
||||
|
||||
#: assets/models/_user.py:55 ops/const.py:49 ops/const.py:59
|
||||
#: assets/models/_user.py:55 ops/const.py:50 ops/const.py:60
|
||||
msgid "Shell"
|
||||
msgstr "Shell"
|
||||
|
||||
|
@ -3594,7 +3594,7 @@ msgstr "准备"
|
|||
msgid "Pending"
|
||||
msgstr "待定的"
|
||||
|
||||
#: common/const/choices.py:17 ops/const.py:71
|
||||
#: common/const/choices.py:17 ops/const.py:72
|
||||
msgid "Running"
|
||||
msgstr "运行中"
|
||||
|
||||
|
@ -4003,6 +4003,10 @@ msgstr "任务 {} 不存在"
|
|||
msgid "Task {} args or kwargs error"
|
||||
msgstr "任务 {} 执行参数错误"
|
||||
|
||||
#: ops/api/job.py:128
|
||||
msgid "Duplicate file exists"
|
||||
msgstr "存在同名文件"
|
||||
|
||||
#: ops/api/playbook.py:39
|
||||
msgid "Currently playbook is being used in a job"
|
||||
msgstr "当前 playbook 正在作业中使用"
|
||||
|
@ -4075,47 +4079,51 @@ msgstr "命令"
|
|||
msgid "Playbook"
|
||||
msgstr "Playbook"
|
||||
|
||||
#: ops/const.py:43
|
||||
#: ops/const.py:40
|
||||
msgid "Upload File"
|
||||
msgstr "上传"
|
||||
|
||||
#: ops/const.py:44
|
||||
msgid "Privileged Only"
|
||||
msgstr "仅限特权账号"
|
||||
|
||||
#: ops/const.py:44
|
||||
#: ops/const.py:45
|
||||
msgid "Privileged First"
|
||||
msgstr "特权账号优先"
|
||||
|
||||
#: ops/const.py:50 ops/const.py:60
|
||||
#: ops/const.py:51 ops/const.py:61
|
||||
msgid "Powershell"
|
||||
msgstr "PowerShell"
|
||||
|
||||
#: ops/const.py:51 ops/const.py:61
|
||||
#: ops/const.py:52 ops/const.py:62
|
||||
msgid "Python"
|
||||
msgstr "Python"
|
||||
|
||||
#: ops/const.py:52 ops/const.py:62
|
||||
#: ops/const.py:53 ops/const.py:63
|
||||
msgid "MySQL"
|
||||
msgstr "MySQL"
|
||||
|
||||
#: ops/const.py:53 ops/const.py:64
|
||||
#: ops/const.py:54 ops/const.py:65
|
||||
msgid "PostgreSQL"
|
||||
msgstr "PostgreSQL"
|
||||
|
||||
#: ops/const.py:54 ops/const.py:65
|
||||
#: ops/const.py:55 ops/const.py:66
|
||||
msgid "SQLServer"
|
||||
msgstr "SQLServer"
|
||||
|
||||
#: ops/const.py:55 ops/const.py:67
|
||||
#: ops/const.py:56 ops/const.py:68
|
||||
msgid "Raw"
|
||||
msgstr "Raw"
|
||||
|
||||
#: ops/const.py:63
|
||||
#: ops/const.py:64
|
||||
msgid "MariaDB"
|
||||
msgstr "MariaDB"
|
||||
|
||||
#: ops/const.py:66
|
||||
#: ops/const.py:67
|
||||
msgid "Oracle"
|
||||
msgstr "Oracle"
|
||||
|
||||
#: ops/const.py:73
|
||||
#: ops/const.py:74
|
||||
msgid "Timeout"
|
||||
msgstr "超时"
|
||||
|
||||
|
@ -4249,7 +4257,7 @@ msgstr "Material"
|
|||
msgid "Material Type"
|
||||
msgstr "Material 类型"
|
||||
|
||||
#: ops/models/job.py:557
|
||||
#: ops/models/job.py:565
|
||||
msgid "Job Execution"
|
||||
msgstr "作业执行"
|
||||
|
||||
|
@ -4293,15 +4301,15 @@ msgstr "CPU 使用率超过 {max_threshold}: => {value}"
|
|||
msgid "Run after save"
|
||||
msgstr "保存后执行"
|
||||
|
||||
#: ops/serializers/job.py:53
|
||||
#: ops/serializers/job.py:63
|
||||
msgid "Job type"
|
||||
msgstr "任务类型"
|
||||
|
||||
#: ops/serializers/job.py:56 terminal/serializers/session.py:53
|
||||
#: ops/serializers/job.py:66 terminal/serializers/session.py:53
|
||||
msgid "Is finished"
|
||||
msgstr "是否完成"
|
||||
|
||||
#: ops/serializers/job.py:57
|
||||
#: ops/serializers/job.py:67
|
||||
msgid "Time cost"
|
||||
msgstr "花费时间"
|
||||
|
||||
|
@ -4516,7 +4524,8 @@ msgstr "授权账号"
|
|||
msgid "today"
|
||||
msgstr "今天"
|
||||
|
||||
#: perms/notifications.py:12 settings/serializers/feature.py:106
|
||||
#: perms/notifications.py:12 perms/notifications.py:44
|
||||
#: settings/serializers/feature.py:106
|
||||
msgid "day"
|
||||
msgstr "天"
|
||||
|
||||
|
@ -4545,20 +4554,6 @@ msgid "Send asset permission expired notification"
|
|||
msgstr "发送资产权限过期通知"
|
||||
|
||||
#: perms/templates/perms/_msg_item_permissions_expire.html:7
|
||||
#, fuzzy, python-format
|
||||
#| msgid ""
|
||||
#| "\n"
|
||||
#| " The following %(item_type)s will expire in %(count)s\n"
|
||||
#| " "
|
||||
msgid ""
|
||||
"\n"
|
||||
" The following %(item_type)s will expire in %(count)s days\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" 以下 %(item_type)s 即将在 %(count)s 后过期\n"
|
||||
" "
|
||||
|
||||
#: perms/templates/perms/_msg_permed_items_expire.html:7
|
||||
#, python-format
|
||||
msgid ""
|
||||
|
@ -8801,6 +8796,7 @@ msgstr "企业专业版"
|
|||
msgid "Ultimate edition"
|
||||
msgstr "企业旗舰版"
|
||||
|
||||
|
||||
#~ msgid "FeiShu query user failed"
|
||||
#~ msgstr "飞书查询用户失败"
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import os
|
||||
import uuid
|
||||
|
||||
import shutil
|
||||
import ansible_runner
|
||||
from django.conf import settings
|
||||
from django.utils._os import safe_join
|
||||
|
||||
from .callback import DefaultCallback
|
||||
from ..utils import get_ansible_log_verbosity
|
||||
|
@ -85,6 +86,34 @@ class PlaybookRunner:
|
|||
return self.cb
|
||||
|
||||
|
||||
class UploadFileRunner:
|
||||
def __init__(self, inventory, job_id, dest_path, callback=None):
|
||||
self.id = uuid.uuid4()
|
||||
self.inventory = inventory
|
||||
self.cb = DefaultCallback()
|
||||
upload_file_dir = safe_join(settings.DATA_DIR, 'job_upload_file')
|
||||
self.src_paths = safe_join(upload_file_dir, str(job_id))
|
||||
self.dest_path = dest_path
|
||||
|
||||
def run(self, verbosity=0, **kwargs):
|
||||
verbosity = get_ansible_log_verbosity(verbosity)
|
||||
ansible_runner.run(
|
||||
host_pattern="*",
|
||||
inventory=self.inventory,
|
||||
module='copy',
|
||||
module_args=f"src={self.src_paths}/ dest={self.dest_path}",
|
||||
verbosity=verbosity,
|
||||
event_handler=self.cb.event_handler,
|
||||
status_handler=self.cb.status_handler,
|
||||
**kwargs
|
||||
)
|
||||
try:
|
||||
shutil.rmtree(self.src_paths)
|
||||
except OSError as e:
|
||||
print(f"del upload tmp dir {self.src_paths} failed! {e}")
|
||||
return self.cb
|
||||
|
||||
|
||||
class CommandRunner(AdHocRunner):
|
||||
def __init__(self, inventory, command, pattern='*', project_dir='/tmp/'):
|
||||
super().__init__(inventory, 'shell', command, pattern, project_dir)
|
||||
|
|
|
@ -1,16 +1,22 @@
|
|||
import json
|
||||
import os
|
||||
from django.conf import settings
|
||||
from django.db import transaction
|
||||
from django.db.models import Count
|
||||
from django.db.transaction import atomic
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils._os import safe_join
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from assets.models import Asset
|
||||
from common.const.http import POST
|
||||
from common.permissions import IsValidUser
|
||||
from ops.const import Types
|
||||
from ops.models import Job, JobExecution
|
||||
from ops.serializers.job import JobSerializer, JobExecutionSerializer
|
||||
from ops.serializers.job import JobSerializer, JobExecutionSerializer, FileSerializer
|
||||
|
||||
__all__ = [
|
||||
'JobViewSet', 'JobExecutionViewSet', 'JobRunVariableHelpAPIView',
|
||||
|
@ -24,6 +30,7 @@ from orgs.utils import tmp_to_org, get_current_org
|
|||
from accounts.models import Account
|
||||
from perms.models import PermNode
|
||||
from perms.utils import UserPermAssetUtil
|
||||
from jumpserver.settings import get_file_md5
|
||||
|
||||
|
||||
def set_task_to_serializer_data(serializer, task_id):
|
||||
|
@ -91,6 +98,40 @@ class JobViewSet(OrgBulkModelViewSet):
|
|||
transaction.on_commit(
|
||||
lambda: run_ops_job_execution.apply_async((str(execution.id),), task_id=str(execution.id)))
|
||||
|
||||
@action(methods=[POST], detail=False, serializer_class=FileSerializer, permission_classes=[IsValidUser, ],
|
||||
url_path='upload')
|
||||
def upload(self, request, *args, **kwargs):
|
||||
serializer = self.get_serializer(data=request.data)
|
||||
if not serializer.is_valid():
|
||||
msg = 'Upload data invalid: {}'.format(serializer.errors)
|
||||
return Response({'msg': msg}, status=400)
|
||||
uploaded_files = request.FILES.getlist('files')
|
||||
job_id = request.data.get('job_id', '')
|
||||
job = get_object_or_404(Job, pk=job_id)
|
||||
job_args = json.loads(job.args)
|
||||
src_path_info = []
|
||||
filename_set = set()
|
||||
same_filenames = []
|
||||
upload_file_dir = safe_join(settings.DATA_DIR, 'job_upload_file')
|
||||
for uploaded_file in uploaded_files:
|
||||
filename = uploaded_file.name
|
||||
saved_path = safe_join(upload_file_dir, f'{job_id}/{filename}')
|
||||
os.makedirs(os.path.dirname(saved_path), exist_ok=True)
|
||||
with open(saved_path, 'wb+') as destination:
|
||||
for chunk in uploaded_file.chunks():
|
||||
destination.write(chunk)
|
||||
if filename in filename_set:
|
||||
same_filenames.append(filename)
|
||||
filename_set.add(filename)
|
||||
src_path_info.append({'filename': filename, 'md5': get_file_md5(saved_path)})
|
||||
if same_filenames:
|
||||
return Response({'msg': _("Duplicate file exists")}, status=400)
|
||||
job_args['src_path_info'] = src_path_info
|
||||
job.args = json.dumps(job_args)
|
||||
job.save()
|
||||
self.run_job(job, serializer)
|
||||
return Response({'task_id': serializer.data.get('task_id')}, status=201)
|
||||
|
||||
|
||||
class JobExecutionViewSet(OrgBulkModelViewSet):
|
||||
serializer_class = JobExecutionSerializer
|
||||
|
|
|
@ -37,6 +37,7 @@ class CreateMethods(models.TextChoices):
|
|||
class Types(models.TextChoices):
|
||||
adhoc = 'adhoc', _('Adhoc')
|
||||
playbook = 'playbook', _('Playbook')
|
||||
upload_file = 'upload_file', _('Upload File')
|
||||
|
||||
|
||||
class RunasPolicies(models.TextChoices):
|
||||
|
|
|
@ -23,7 +23,7 @@ from assets.models import Asset
|
|||
from assets.automations.base.manager import SSHTunnelManager
|
||||
from common.db.encoder import ModelJSONFieldEncoder
|
||||
from labels.mixins import LabeledMixin
|
||||
from ops.ansible import JMSInventory, AdHocRunner, PlaybookRunner, CommandInBlackListException
|
||||
from ops.ansible import JMSInventory, AdHocRunner, PlaybookRunner, CommandInBlackListException, UploadFileRunner
|
||||
from ops.mixin import PeriodTaskModelMixin
|
||||
from ops.variables import *
|
||||
from ops.const import Types, RunasPolicies, JobStatus, JobModules
|
||||
|
@ -362,7 +362,7 @@ class JobExecution(JMSOrgBaseModel):
|
|||
static_variables = self.gather_static_variables()
|
||||
extra_vars.update(static_variables)
|
||||
|
||||
if self.current_job.type == 'adhoc':
|
||||
if self.current_job.type == Types.adhoc:
|
||||
module, args = self.compile_shell()
|
||||
|
||||
runner = AdHocRunner(
|
||||
|
@ -374,10 +374,18 @@ class JobExecution(JMSOrgBaseModel):
|
|||
project_dir=self.private_dir,
|
||||
extra_vars=extra_vars,
|
||||
)
|
||||
elif self.current_job.type == 'playbook':
|
||||
elif self.current_job.type == Types.playbook:
|
||||
runner = PlaybookRunner(
|
||||
self.inventory_path, self.current_job.playbook.entry
|
||||
)
|
||||
elif self.current_job.type == Types.upload_file:
|
||||
job_id = self.current_job.id
|
||||
args = json.loads(self.current_job.args)
|
||||
dst_path = args.get('dst_path')
|
||||
if dst_path:
|
||||
runner = UploadFileRunner(self.inventory_path, job_id, dst_path)
|
||||
else:
|
||||
raise ValueError("dst_path is null")
|
||||
else:
|
||||
raise Exception("unsupported job type")
|
||||
return runner
|
||||
|
|
|
@ -21,9 +21,12 @@ class JobSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer, PeriodT
|
|||
|
||||
def to_internal_value(self, data):
|
||||
instant = data.get('instant', False)
|
||||
job_type = data.get('type', '')
|
||||
_uid = str(uuid.uuid4()).split('-')[-1]
|
||||
if instant:
|
||||
_uid = str(uuid.uuid4()).split('-')[-1]
|
||||
data['name'] = f'job-{_uid}'
|
||||
if job_type == 'upload_file':
|
||||
data['name'] = f'upload_file-{_uid}'
|
||||
return super().to_internal_value(data)
|
||||
|
||||
def get_request_user(self):
|
||||
|
@ -44,10 +47,17 @@ class JobSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer, PeriodT
|
|||
"use_parameter_define", "parameters_define",
|
||||
"timeout", "chdir", "comment", "summary",
|
||||
"is_periodic", "interval", "crontab", "nodes",
|
||||
"run_after_save",
|
||||
"run_after_save"
|
||||
]
|
||||
|
||||
|
||||
class FileSerializer(serializers.Serializer):
|
||||
files = serializers.FileField(allow_empty_file=True)
|
||||
|
||||
class Meta:
|
||||
ref_name = "JobFileSerializer"
|
||||
|
||||
|
||||
class JobExecutionSerializer(BulkOrgResourceModelSerializer):
|
||||
creator = ReadableHiddenField(default=serializers.CurrentUserDefault())
|
||||
job_type = serializers.ReadOnlyField(label=_("Job type"))
|
||||
|
|
|
@ -41,7 +41,7 @@ class AssetPermsWillExpireForOrgAdminMsg(UserMessage):
|
|||
super().__init__(user)
|
||||
self.perms = perms
|
||||
self.org = org
|
||||
self.day_count = _('today') if day_count == 0 else day_count
|
||||
self.day_count = _('today') if day_count == 0 else day_count + _('day')
|
||||
|
||||
def get_items_with_url(self):
|
||||
items_with_url = []
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<p>
|
||||
{% blocktranslate %}
|
||||
The following {{ item_type }} will expire in {{ count }} days
|
||||
The following {{ item_type }} will expire in {{ count }}
|
||||
{% endblocktranslate %}
|
||||
</p>
|
||||
|
||||
|
|
Loading…
Reference in New Issue