mirror of https://github.com/jumpserver/jumpserver
commit
a9620a3cbe
|
@ -94,7 +94,8 @@ JumpServer 堡垒机帮助企业以更安全的方式管控和登录各种类型
|
||||||
| [KoKo](https://github.com/jumpserver/koko) | <a href="https://github.com/jumpserver/koko/releases"><img alt="Koko release" src="https://img.shields.io/github/release/jumpserver/koko.svg" /></a> | JumpServer 字符协议 Connector 项目 |
|
| [KoKo](https://github.com/jumpserver/koko) | <a href="https://github.com/jumpserver/koko/releases"><img alt="Koko release" src="https://img.shields.io/github/release/jumpserver/koko.svg" /></a> | JumpServer 字符协议 Connector 项目 |
|
||||||
| [Lion](https://github.com/jumpserver/lion-release) | <a href="https://github.com/jumpserver/lion-release/releases"><img alt="Lion release" src="https://img.shields.io/github/release/jumpserver/lion-release.svg" /></a> | JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/) |
|
| [Lion](https://github.com/jumpserver/lion-release) | <a href="https://github.com/jumpserver/lion-release/releases"><img alt="Lion release" src="https://img.shields.io/github/release/jumpserver/lion-release.svg" /></a> | JumpServer 图形协议 Connector 项目,依赖 [Apache Guacamole](https://guacamole.apache.org/) |
|
||||||
| [Razor](https://github.com/jumpserver/razor) | <img alt="Chen" src="https://img.shields.io/badge/release-私有发布-red" /> | JumpServer RDP 代理 Connector 项目 |
|
| [Razor](https://github.com/jumpserver/razor) | <img alt="Chen" src="https://img.shields.io/badge/release-私有发布-red" /> | JumpServer RDP 代理 Connector 项目 |
|
||||||
| [Tinker](https://github.com/jumpserver/tinker) | <img alt="Tinker" src="https://img.shields.io/badge/release-私有发布-red" /> | JumpServer 远程应用 Connector 项目 |
|
| [Tinker](https://github.com/jumpserver/tinker) | <img alt="Tinker" src="https://img.shields.io/badge/release-私有发布-red" /> | JumpServer 远程应用 Connector 项目 (Windows) |
|
||||||
|
| [Panda](https://github.com/jumpserver/Panda) | <img alt="Panda" src="https://img.shields.io/badge/release-私有发布-red" /> | JumpServer 远程应用 Connector 项目 (Linux) |
|
||||||
| [Magnus](https://github.com/jumpserver/magnus-release) | <a href="https://github.com/jumpserver/magnus-release/releases"><img alt="Magnus release" src="https://img.shields.io/github/release/jumpserver/magnus-release.svg" /> | JumpServer 数据库代理 Connector 项目 |
|
| [Magnus](https://github.com/jumpserver/magnus-release) | <a href="https://github.com/jumpserver/magnus-release/releases"><img alt="Magnus release" src="https://img.shields.io/github/release/jumpserver/magnus-release.svg" /> | JumpServer 数据库代理 Connector 项目 |
|
||||||
| [Chen](https://github.com/jumpserver/chen-release) | <a href="https://github.com/jumpserver/chen-release/releases"><img alt="Chen release" src="https://img.shields.io/github/release/jumpserver/chen-release.svg" /> | JumpServer Web DB 项目,替代原来的 OmniDB |
|
| [Chen](https://github.com/jumpserver/chen-release) | <a href="https://github.com/jumpserver/chen-release/releases"><img alt="Chen release" src="https://img.shields.io/github/release/jumpserver/chen-release.svg" /> | JumpServer Web DB 项目,替代原来的 OmniDB |
|
||||||
| [Kael](https://github.com/jumpserver/kael) | <a href="https://github.com/jumpserver/kael/releases"><img alt="Kael release" src="https://img.shields.io/github/release/jumpserver/kael.svg" /> | JumpServer 连接 GPT 资产的组件项目 |
|
| [Kael](https://github.com/jumpserver/kael) | <a href="https://github.com/jumpserver/kael/releases"><img alt="Kael release" src="https://img.shields.io/github/release/jumpserver/kael.svg" /> | JumpServer 连接 GPT 资产的组件项目 |
|
||||||
|
|
|
@ -3,13 +3,13 @@ import time
|
||||||
from collections import defaultdict, OrderedDict
|
from collections import defaultdict, OrderedDict
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from openpyxl import Workbook
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from xlsxwriter import Workbook
|
||||||
|
|
||||||
from accounts.const.automation import AccountBackupType
|
from accounts.const.automation import AccountBackupType
|
||||||
|
from accounts.models.automations.backup_account import AccountBackupAutomation
|
||||||
from accounts.notifications import AccountBackupExecutionTaskMsg, AccountBackupByObjStorageExecutionTaskMsg
|
from accounts.notifications import AccountBackupExecutionTaskMsg, AccountBackupByObjStorageExecutionTaskMsg
|
||||||
from accounts.serializers import AccountSecretSerializer
|
from accounts.serializers import AccountSecretSerializer
|
||||||
from accounts.models.automations.backup_account import AccountBackupAutomation
|
|
||||||
from assets.const import AllTypes
|
from assets.const import AllTypes
|
||||||
from common.utils.file import encrypt_and_compress_zip_file, zip_files
|
from common.utils.file import encrypt_and_compress_zip_file, zip_files
|
||||||
from common.utils.timezone import local_now_filename, local_now_display
|
from common.utils.timezone import local_now_filename, local_now_display
|
||||||
|
@ -144,10 +144,11 @@ class AccountBackupHandler:
|
||||||
|
|
||||||
wb = Workbook(filename)
|
wb = Workbook(filename)
|
||||||
for sheet, data in data_map.items():
|
for sheet, data in data_map.items():
|
||||||
ws = wb.create_sheet(str(sheet))
|
ws = wb.add_worksheet(str(sheet))
|
||||||
for row in data:
|
for row in data:
|
||||||
ws.append(row)
|
for col, _data in enumerate(row):
|
||||||
wb.save(filename)
|
ws.write_string(0, col, _data)
|
||||||
|
wb.close()
|
||||||
files.append(filename)
|
files.append(filename)
|
||||||
timedelta = round((time.time() - time_start), 2)
|
timedelta = round((time.time() - time_start), 2)
|
||||||
print('创建备份文件完成: 用时 {}s'.format(timedelta))
|
print('创建备份文件完成: 用时 {}s'.format(timedelta))
|
||||||
|
|
|
@ -4,7 +4,7 @@ from copy import deepcopy
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from openpyxl import Workbook
|
from xlsxwriter import Workbook
|
||||||
|
|
||||||
from accounts.const import AutomationTypes, SecretType, SSHKeyStrategy, SecretStrategy
|
from accounts.const import AutomationTypes, SecretType, SSHKeyStrategy, SecretStrategy
|
||||||
from accounts.models import ChangeSecretRecord
|
from accounts.models import ChangeSecretRecord
|
||||||
|
@ -227,8 +227,9 @@ class ChangeSecretManager(AccountBasePlaybookManager):
|
||||||
|
|
||||||
rows.insert(0, header)
|
rows.insert(0, header)
|
||||||
wb = Workbook(filename)
|
wb = Workbook(filename)
|
||||||
ws = wb.create_sheet('Sheet1')
|
ws = wb.add_worksheet('Sheet1')
|
||||||
for row in rows:
|
for row in rows:
|
||||||
ws.append(row)
|
for col, data in enumerate(row):
|
||||||
wb.save(filename)
|
ws.write_string(0, col, data)
|
||||||
|
wb.close()
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -72,7 +72,7 @@ class GatherAccountsManager(AccountBasePlaybookManager):
|
||||||
)
|
)
|
||||||
gathered_accounts.append(gathered_account)
|
gathered_accounts.append(gathered_account)
|
||||||
if not self.is_sync_account:
|
if not self.is_sync_account:
|
||||||
return
|
continue
|
||||||
GatheredAccount.sync_accounts(gathered_accounts)
|
GatheredAccount.sync_accounts(gathered_accounts)
|
||||||
|
|
||||||
def run(self, *args, **kwargs):
|
def run(self, *args, **kwargs):
|
||||||
|
|
|
@ -16,10 +16,11 @@
|
||||||
- name: "Rename user home directory if it exists"
|
- name: "Rename user home directory if it exists"
|
||||||
ansible.builtin.command:
|
ansible.builtin.command:
|
||||||
cmd: "mv {{ user_home_dir.stdout }} {{ user_home_dir.stdout }}.bak"
|
cmd: "mv {{ user_home_dir.stdout }} {{ user_home_dir.stdout }}.bak"
|
||||||
when: home_dir.stat.exists and user_home_dir.stdout != ""
|
when: home_dir.stat | default(false) and user_home_dir.stdout != ""
|
||||||
|
|
||||||
- name: "Remove account"
|
- name: "Remove account"
|
||||||
ansible.builtin.user:
|
ansible.builtin.user:
|
||||||
name: "{{ account.username }}"
|
name: "{{ account.username }}"
|
||||||
state: absent
|
state: absent
|
||||||
remove: "{{ home_dir.stat.exists }}"
|
remove: "{{ home_dir.stat.exists }}"
|
||||||
|
when: home_dir.stat | default(false)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from accounts.models import Account
|
||||||
from assets.models import Asset
|
from assets.models import Asset
|
||||||
from audits.models import UserLoginLog
|
from audits.models import UserLoginLog
|
||||||
from notifications.notifications import UserMessage
|
from notifications.notifications import UserMessage
|
||||||
|
@ -16,12 +17,11 @@ class UserLoginReminderMsg(UserMessage):
|
||||||
|
|
||||||
def get_html_msg(self) -> dict:
|
def get_html_msg(self) -> dict:
|
||||||
user_log = self.user_log
|
user_log = self.user_log
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
'ip': user_log.ip,
|
'ip': user_log.ip,
|
||||||
'city': user_log.city,
|
'city': user_log.city,
|
||||||
'username': user_log.username,
|
'username': user_log.username,
|
||||||
'recipient': self.user.username,
|
'recipient': self.user,
|
||||||
'user_agent': user_log.user_agent,
|
'user_agent': user_log.user_agent,
|
||||||
}
|
}
|
||||||
message = render_to_string('acls/user_login_reminder.html', context)
|
message = render_to_string('acls/user_login_reminder.html', context)
|
||||||
|
@ -48,11 +48,14 @@ class AssetLoginReminderMsg(UserMessage):
|
||||||
super().__init__(user)
|
super().__init__(user)
|
||||||
|
|
||||||
def get_html_msg(self) -> dict:
|
def get_html_msg(self) -> dict:
|
||||||
|
account = Account.objects.get(asset=self.asset, username=self.account_username)
|
||||||
context = {
|
context = {
|
||||||
'recipient': self.user.username,
|
'recipient': self.user,
|
||||||
'username': self.login_user.username,
|
'username': self.login_user.username,
|
||||||
|
'name': self.login_user.name,
|
||||||
'asset': str(self.asset),
|
'asset': str(self.asset),
|
||||||
'account': self.account_username,
|
'account': self.account_username,
|
||||||
|
'account_name': account.name,
|
||||||
}
|
}
|
||||||
message = render_to_string('acls/asset_login_reminder.html', context)
|
message = render_to_string('acls/asset_login_reminder.html', context)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
<h3>{% trans 'Respectful' %}{{ recipient }},</h3>
|
<h3>{% trans 'Respectful' %}: {{ recipient.name }}[{{ recipient.username }}]</h3>
|
||||||
<hr>
|
<hr>
|
||||||
<p><strong>{% trans 'Username' %}:</strong> [{{ username }}]</p>
|
<p><strong>{% trans 'User' %}:</strong> [{{ name }}({{ username }})]</p>
|
||||||
<p><strong>{% trans 'Assets' %}:</strong> [{{ asset }}]</p>
|
<p><strong>{% trans 'Assets' %}:</strong> [{{ asset }}]</p>
|
||||||
<p><strong>{% trans 'Account' %}:</strong> [{{ account }}]</p>
|
<p><strong>{% trans 'Account' %}:</strong> [{{ account_name }}({{ account }})]</p>
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<p>{% trans 'The user has just logged in to the asset. Please ensure that this is an authorized operation. If you suspect that this is an unauthorized access, please take appropriate measures immediately.' %}</p>
|
<p>{% trans 'The user has just logged in to the asset. Please ensure that this is an authorized operation. If you suspect that this is an unauthorized access, please take appropriate measures immediately.' %}</p>
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
{% load i18n %}
|
{% load i18n %}
|
||||||
|
|
||||||
<h3>{% trans 'Respectful' %}{{ recipient }},</h3>
|
<h3>{% trans 'Respectful' %}: {{ recipient.name }}[{{ recipient.username }}]</h3>
|
||||||
<hr>
|
<hr>
|
||||||
<p><strong>{% trans 'Username' %}:</strong> [{{ username }}]</p>
|
<p><strong>{% trans 'User' %}:</strong> [{{ username }}]</p>
|
||||||
<p><strong>IP:</strong> [{{ ip }}]</p>
|
<p><strong>IP:</strong> [{{ ip }}]</p>
|
||||||
<p><strong>{% trans 'Login city' %}:</strong> [{{ city }}]</p>
|
<p><strong>{% trans 'Login city' %}:</strong> [{{ city }}]</p>
|
||||||
<p><strong>{% trans 'User agent' %}:</strong> [{{ user_agent }}]</p>
|
<p><strong>{% trans 'User agent' %}:</strong> [{{ user_agent }}]</p>
|
||||||
|
|
|
@ -93,7 +93,7 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet):
|
||||||
model = Asset
|
model = Asset
|
||||||
filterset_class = AssetFilterSet
|
filterset_class = AssetFilterSet
|
||||||
search_fields = ("name", "address", "comment")
|
search_fields = ("name", "address", "comment")
|
||||||
ordering_fields = ('name', 'connectivity', 'platform', 'date_updated', 'date_created')
|
ordering_fields = ('name', 'address', 'connectivity', 'platform', 'date_updated', 'date_created')
|
||||||
serializer_classes = (
|
serializer_classes = (
|
||||||
("default", serializers.AssetSerializer),
|
("default", serializers.AssetSerializer),
|
||||||
("platform", serializers.PlatformSerializer),
|
("platform", serializers.PlatformSerializer),
|
||||||
|
|
|
@ -122,7 +122,8 @@ def send_login_info_to_reviewers(instance: UserLoginLog | str, auth_acl_id):
|
||||||
def on_user_auth_success(sender, user, request, login_type=None, **kwargs):
|
def on_user_auth_success(sender, user, request, login_type=None, **kwargs):
|
||||||
logger.debug('User login success: {}'.format(user.username))
|
logger.debug('User login success: {}'.format(user.username))
|
||||||
check_different_city_login_if_need(user, request)
|
check_different_city_login_if_need(user, request)
|
||||||
data = generate_data(user.username, request, login_type=login_type)
|
username = f"{user.name}({user.username})"
|
||||||
|
data = generate_data(username, request, login_type=login_type)
|
||||||
request.session['login_time'] = data['datetime'].strftime('%Y-%m-%d %H:%M:%S')
|
request.session['login_time'] = data['datetime'].strftime('%Y-%m-%d %H:%M:%S')
|
||||||
data.update({'mfa': int(user.mfa_enabled), 'status': True})
|
data.update({'mfa': int(user.mfa_enabled), 'status': True})
|
||||||
instance = write_login_log(**data)
|
instance = write_login_log(**data)
|
||||||
|
|
|
@ -152,6 +152,8 @@ class SessionCookieMiddleware(MiddlewareMixin):
|
||||||
value = 'close'
|
value = 'close'
|
||||||
|
|
||||||
age = request.session.get_expiry_age()
|
age = request.session.get_expiry_age()
|
||||||
|
expire_timestamp = request.session.get_expiry_date().timestamp()
|
||||||
|
response.set_cookie('jms_session_expire_timestamp', expire_timestamp)
|
||||||
response.set_cookie('jms_session_expire', value, max_age=age)
|
response.set_cookie('jms_session_expire', value, max_age=age)
|
||||||
request.session.pop('auth_session_expiration_required', None)
|
request.session.pop('auth_session_expiration_required', None)
|
||||||
|
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
|
from jumpserver.rewriting import db # noqa 采用猴子补丁的方式,重写atomic ForeignKey OneToOneField
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
from . import db
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-12-21 16:12+0800\n"
|
"POT-Creation-Date: 2023-12-26 14:13+0800\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
@ -476,7 +476,7 @@ msgstr "終了日"
|
||||||
#: accounts/models/automations/change_secret.py:43
|
#: accounts/models/automations/change_secret.py:43
|
||||||
#: assets/models/automations/base.py:113 audits/models.py:208
|
#: assets/models/automations/base.py:113 audits/models.py:208
|
||||||
#: audits/serializers.py:54 ops/models/base.py:49 ops/models/job.py:227
|
#: audits/serializers.py:54 ops/models/base.py:49 ops/models/job.py:227
|
||||||
#: terminal/models/applet/applet.py:319 terminal/models/applet/host.py:140
|
#: terminal/models/applet/applet.py:320 terminal/models/applet/host.py:140
|
||||||
#: terminal/models/component/status.py:30
|
#: terminal/models/component/status.py:30
|
||||||
#: terminal/models/virtualapp/virtualapp.py:99
|
#: terminal/models/virtualapp/virtualapp.py:99
|
||||||
#: terminal/serializers/applet.py:18 terminal/serializers/applet_host.py:136
|
#: terminal/serializers/applet.py:18 terminal/serializers/applet_host.py:136
|
||||||
|
@ -742,7 +742,7 @@ msgstr "アカウントの存在ポリシー"
|
||||||
#: assets/models/label.py:21 assets/models/platform.py:96
|
#: assets/models/label.py:21 assets/models/platform.py:96
|
||||||
#: assets/serializers/asset/common.py:122 assets/serializers/cagegory.py:12
|
#: assets/serializers/asset/common.py:122 assets/serializers/cagegory.py:12
|
||||||
#: assets/serializers/platform.py:140 assets/serializers/platform.py:236
|
#: assets/serializers/platform.py:140 assets/serializers/platform.py:236
|
||||||
#: perms/serializers/user_permission.py:25 settings/models.py:35
|
#: perms/serializers/user_permission.py:26 settings/models.py:35
|
||||||
#: tickets/models/ticket/apply_application.py:13 users/models/preference.py:12
|
#: tickets/models/ticket/apply_application.py:13 users/models/preference.py:12
|
||||||
msgid "Category"
|
msgid "Category"
|
||||||
msgstr "カテゴリ"
|
msgstr "カテゴリ"
|
||||||
|
@ -756,7 +756,7 @@ msgstr "カテゴリ"
|
||||||
#: assets/serializers/platform.py:139 audits/serializers.py:53
|
#: assets/serializers/platform.py:139 audits/serializers.py:53
|
||||||
#: audits/serializers.py:170
|
#: audits/serializers.py:170
|
||||||
#: authentication/serializers/connect_token_secret.py:126 ops/models/job.py:144
|
#: authentication/serializers/connect_token_secret.py:126 ops/models/job.py:144
|
||||||
#: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:39
|
#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:39
|
||||||
#: terminal/models/component/storage.py:57
|
#: terminal/models/component/storage.py:57
|
||||||
#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29
|
#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29
|
||||||
#: terminal/serializers/session.py:21 terminal/serializers/storage.py:264
|
#: terminal/serializers/session.py:21 terminal/serializers/storage.py:264
|
||||||
|
@ -923,7 +923,7 @@ msgstr "关联平台,可以配置推送参数,如果不关联,则使用默
|
||||||
#: assets/models/group.py:20 common/db/models.py:36 ops/models/adhoc.py:26
|
#: assets/models/group.py:20 common/db/models.py:36 ops/models/adhoc.py:26
|
||||||
#: ops/models/job.py:152 ops/models/playbook.py:31 rbac/models/role.py:37
|
#: ops/models/job.py:152 ops/models/playbook.py:31 rbac/models/role.py:37
|
||||||
#: settings/models.py:38 terminal/models/applet/applet.py:45
|
#: settings/models.py:38 terminal/models/applet/applet.py:45
|
||||||
#: terminal/models/applet/applet.py:320 terminal/models/applet/host.py:143
|
#: terminal/models/applet/applet.py:321 terminal/models/applet/host.py:143
|
||||||
#: terminal/models/component/endpoint.py:25
|
#: terminal/models/component/endpoint.py:25
|
||||||
#: terminal/models/component/endpoint.py:105
|
#: terminal/models/component/endpoint.py:105
|
||||||
#: terminal/models/session/session.py:46
|
#: terminal/models/session/session.py:46
|
||||||
|
@ -1720,7 +1720,7 @@ msgstr "アドレス"
|
||||||
#: assets/models/asset/common.py:161 assets/models/platform.py:126
|
#: assets/models/asset/common.py:161 assets/models/platform.py:126
|
||||||
#: authentication/backends/passkey/models.py:12
|
#: authentication/backends/passkey/models.py:12
|
||||||
#: authentication/serializers/connect_token_secret.py:118
|
#: authentication/serializers/connect_token_secret.py:118
|
||||||
#: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:329
|
#: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:329
|
||||||
msgid "Platform"
|
msgid "Platform"
|
||||||
msgstr "プラットフォーム"
|
msgstr "プラットフォーム"
|
||||||
|
|
||||||
|
@ -1886,8 +1886,7 @@ msgstr "値"
|
||||||
#: assets/serializers/platform.py:119
|
#: assets/serializers/platform.py:119
|
||||||
#: authentication/serializers/connect_token_secret.py:124
|
#: authentication/serializers/connect_token_secret.py:124
|
||||||
#: common/serializers/common.py:85 labels/models.py:17 labels/models.py:33
|
#: common/serializers/common.py:85 labels/models.py:17 labels/models.py:33
|
||||||
#: labels/serializers.py:45 perms/serializers/user_permission.py:27
|
#: labels/serializers.py:45 settings/serializers/msg.py:83
|
||||||
#: settings/serializers/msg.py:83
|
|
||||||
msgid "Label"
|
msgid "Label"
|
||||||
msgstr "ラベル"
|
msgstr "ラベル"
|
||||||
|
|
||||||
|
@ -3707,7 +3706,7 @@ msgid "Invalid ids for ids, should be a list"
|
||||||
msgstr "無効なID、リストでなければなりません"
|
msgstr "無効なID、リストでなければなりません"
|
||||||
|
|
||||||
#: common/db/fields.py:585 common/db/fields.py:590
|
#: common/db/fields.py:585 common/db/fields.py:590
|
||||||
#: common/serializers/fields.py:134 tickets/serializers/ticket/common.py:58
|
#: common/serializers/fields.py:133 tickets/serializers/ticket/common.py:58
|
||||||
#: xpack/plugins/cloud/serializers/account_attrs.py:56
|
#: xpack/plugins/cloud/serializers/account_attrs.py:56
|
||||||
#: xpack/plugins/cloud/serializers/account_attrs.py:79
|
#: xpack/plugins/cloud/serializers/account_attrs.py:79
|
||||||
#: xpack/plugins/cloud/serializers/account_attrs.py:150
|
#: xpack/plugins/cloud/serializers/account_attrs.py:150
|
||||||
|
@ -3880,21 +3879,21 @@ msgstr "{} 秒待ってから送信してください"
|
||||||
msgid "Children"
|
msgid "Children"
|
||||||
msgstr "ノード"
|
msgstr "ノード"
|
||||||
|
|
||||||
#: common/serializers/fields.py:135
|
#: common/serializers/fields.py:134
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Invalid pk \"{pk_value}\" - object does not exist."
|
msgid "Invalid pk \"{pk_value}\" - object does not exist."
|
||||||
msgstr "無効な pk \"{pk_value}\" - オブジェクトが存在しません"
|
msgstr "無効な pk \"{pk_value}\" - オブジェクトが存在しません"
|
||||||
|
|
||||||
#: common/serializers/fields.py:136
|
#: common/serializers/fields.py:135
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Incorrect type. Expected pk value, received {data_type}."
|
msgid "Incorrect type. Expected pk value, received {data_type}."
|
||||||
msgstr "エラータイプ。 予想される pk 値、受信 {data_type}。"
|
msgstr "エラータイプ。 予想される pk 値、受信 {data_type}。"
|
||||||
|
|
||||||
#: common/serializers/fields.py:210
|
#: common/serializers/fields.py:209
|
||||||
msgid "Invalid data type, should be list"
|
msgid "Invalid data type, should be list"
|
||||||
msgstr "間違ったデータ タイプです。リストにする必要があります"
|
msgstr "間違ったデータ タイプです。リストにする必要があります"
|
||||||
|
|
||||||
#: common/serializers/fields.py:225
|
#: common/serializers/fields.py:224
|
||||||
msgid "Invalid choice: {}"
|
msgid "Invalid choice: {}"
|
||||||
msgstr "無効なオプション: {}"
|
msgstr "無効なオプション: {}"
|
||||||
|
|
||||||
|
@ -4815,7 +4814,7 @@ msgid "My assets"
|
||||||
msgstr "私の資産"
|
msgstr "私の資産"
|
||||||
|
|
||||||
#: rbac/tree.py:58 terminal/models/applet/applet.py:52
|
#: rbac/tree.py:58 terminal/models/applet/applet.py:52
|
||||||
#: terminal/models/applet/applet.py:316 terminal/models/applet/host.py:30
|
#: terminal/models/applet/applet.py:317 terminal/models/applet/host.py:30
|
||||||
#: terminal/serializers/applet.py:15
|
#: terminal/serializers/applet.py:15
|
||||||
msgid "Applet"
|
msgid "Applet"
|
||||||
msgstr "リモートアプリケーション"
|
msgstr "リモートアプリケーション"
|
||||||
|
@ -6597,7 +6596,7 @@ msgstr "カスタムプラットフォームのみをサポート"
|
||||||
msgid "Missing type in platform.yml"
|
msgid "Missing type in platform.yml"
|
||||||
msgstr "platform.ymlにタイプがありません"
|
msgstr "platform.ymlにタイプがありません"
|
||||||
|
|
||||||
#: terminal/models/applet/applet.py:318 terminal/models/applet/host.py:36
|
#: terminal/models/applet/applet.py:319 terminal/models/applet/host.py:36
|
||||||
#: terminal/models/applet/host.py:138
|
#: terminal/models/applet/host.py:138
|
||||||
msgid "Hosting"
|
msgid "Hosting"
|
||||||
msgstr "ホスト マシン"
|
msgstr "ホスト マシン"
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:853320b42ac7795fa983c4216f89b3a776a889453d90e11dc425d1388ff9b803
|
oid sha256:80dd11dde678e4f9b64df18906175125218fd9f719bfe9aaa667ad6e2d055d40
|
||||||
size 139012
|
size 139012
|
||||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2023-12-21 16:12+0800\n"
|
"POT-Creation-Date: 2023-12-26 14:13+0800\n"
|
||||||
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
||||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
||||||
|
@ -475,7 +475,7 @@ msgstr "结束日期"
|
||||||
#: accounts/models/automations/change_secret.py:43
|
#: accounts/models/automations/change_secret.py:43
|
||||||
#: assets/models/automations/base.py:113 audits/models.py:208
|
#: assets/models/automations/base.py:113 audits/models.py:208
|
||||||
#: audits/serializers.py:54 ops/models/base.py:49 ops/models/job.py:227
|
#: audits/serializers.py:54 ops/models/base.py:49 ops/models/job.py:227
|
||||||
#: terminal/models/applet/applet.py:319 terminal/models/applet/host.py:140
|
#: terminal/models/applet/applet.py:320 terminal/models/applet/host.py:140
|
||||||
#: terminal/models/component/status.py:30
|
#: terminal/models/component/status.py:30
|
||||||
#: terminal/models/virtualapp/virtualapp.py:99
|
#: terminal/models/virtualapp/virtualapp.py:99
|
||||||
#: terminal/serializers/applet.py:18 terminal/serializers/applet_host.py:136
|
#: terminal/serializers/applet.py:18 terminal/serializers/applet_host.py:136
|
||||||
|
@ -740,7 +740,7 @@ msgstr "账号存在策略"
|
||||||
#: assets/models/label.py:21 assets/models/platform.py:96
|
#: assets/models/label.py:21 assets/models/platform.py:96
|
||||||
#: assets/serializers/asset/common.py:122 assets/serializers/cagegory.py:12
|
#: assets/serializers/asset/common.py:122 assets/serializers/cagegory.py:12
|
||||||
#: assets/serializers/platform.py:140 assets/serializers/platform.py:236
|
#: assets/serializers/platform.py:140 assets/serializers/platform.py:236
|
||||||
#: perms/serializers/user_permission.py:25 settings/models.py:35
|
#: perms/serializers/user_permission.py:26 settings/models.py:35
|
||||||
#: tickets/models/ticket/apply_application.py:13 users/models/preference.py:12
|
#: tickets/models/ticket/apply_application.py:13 users/models/preference.py:12
|
||||||
msgid "Category"
|
msgid "Category"
|
||||||
msgstr "类别"
|
msgstr "类别"
|
||||||
|
@ -754,7 +754,7 @@ msgstr "类别"
|
||||||
#: assets/serializers/platform.py:139 audits/serializers.py:53
|
#: assets/serializers/platform.py:139 audits/serializers.py:53
|
||||||
#: audits/serializers.py:170
|
#: audits/serializers.py:170
|
||||||
#: authentication/serializers/connect_token_secret.py:126 ops/models/job.py:144
|
#: authentication/serializers/connect_token_secret.py:126 ops/models/job.py:144
|
||||||
#: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:39
|
#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:39
|
||||||
#: terminal/models/component/storage.py:57
|
#: terminal/models/component/storage.py:57
|
||||||
#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29
|
#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29
|
||||||
#: terminal/serializers/session.py:21 terminal/serializers/storage.py:264
|
#: terminal/serializers/session.py:21 terminal/serializers/storage.py:264
|
||||||
|
@ -921,7 +921,7 @@ msgstr "关联平台,可配置推送参数,如果不关联,将使用默认
|
||||||
#: assets/models/group.py:20 common/db/models.py:36 ops/models/adhoc.py:26
|
#: assets/models/group.py:20 common/db/models.py:36 ops/models/adhoc.py:26
|
||||||
#: ops/models/job.py:152 ops/models/playbook.py:31 rbac/models/role.py:37
|
#: ops/models/job.py:152 ops/models/playbook.py:31 rbac/models/role.py:37
|
||||||
#: settings/models.py:38 terminal/models/applet/applet.py:45
|
#: settings/models.py:38 terminal/models/applet/applet.py:45
|
||||||
#: terminal/models/applet/applet.py:320 terminal/models/applet/host.py:143
|
#: terminal/models/applet/applet.py:321 terminal/models/applet/host.py:143
|
||||||
#: terminal/models/component/endpoint.py:25
|
#: terminal/models/component/endpoint.py:25
|
||||||
#: terminal/models/component/endpoint.py:105
|
#: terminal/models/component/endpoint.py:105
|
||||||
#: terminal/models/session/session.py:46
|
#: terminal/models/session/session.py:46
|
||||||
|
@ -1712,7 +1712,7 @@ msgstr "地址"
|
||||||
#: assets/models/asset/common.py:161 assets/models/platform.py:126
|
#: assets/models/asset/common.py:161 assets/models/platform.py:126
|
||||||
#: authentication/backends/passkey/models.py:12
|
#: authentication/backends/passkey/models.py:12
|
||||||
#: authentication/serializers/connect_token_secret.py:118
|
#: authentication/serializers/connect_token_secret.py:118
|
||||||
#: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:329
|
#: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:329
|
||||||
msgid "Platform"
|
msgid "Platform"
|
||||||
msgstr "系统平台"
|
msgstr "系统平台"
|
||||||
|
|
||||||
|
@ -1878,8 +1878,7 @@ msgstr "值"
|
||||||
#: assets/serializers/platform.py:119
|
#: assets/serializers/platform.py:119
|
||||||
#: authentication/serializers/connect_token_secret.py:124
|
#: authentication/serializers/connect_token_secret.py:124
|
||||||
#: common/serializers/common.py:85 labels/models.py:17 labels/models.py:33
|
#: common/serializers/common.py:85 labels/models.py:17 labels/models.py:33
|
||||||
#: labels/serializers.py:45 perms/serializers/user_permission.py:27
|
#: labels/serializers.py:45 settings/serializers/msg.py:83
|
||||||
#: settings/serializers/msg.py:83
|
|
||||||
msgid "Label"
|
msgid "Label"
|
||||||
msgstr "标签"
|
msgstr "标签"
|
||||||
|
|
||||||
|
@ -3663,7 +3662,7 @@ msgid "Invalid ids for ids, should be a list"
|
||||||
msgstr "无效的ID,应为列表"
|
msgstr "无效的ID,应为列表"
|
||||||
|
|
||||||
#: common/db/fields.py:585 common/db/fields.py:590
|
#: common/db/fields.py:585 common/db/fields.py:590
|
||||||
#: common/serializers/fields.py:134 tickets/serializers/ticket/common.py:58
|
#: common/serializers/fields.py:133 tickets/serializers/ticket/common.py:58
|
||||||
#: xpack/plugins/cloud/serializers/account_attrs.py:56
|
#: xpack/plugins/cloud/serializers/account_attrs.py:56
|
||||||
#: xpack/plugins/cloud/serializers/account_attrs.py:79
|
#: xpack/plugins/cloud/serializers/account_attrs.py:79
|
||||||
#: xpack/plugins/cloud/serializers/account_attrs.py:150
|
#: xpack/plugins/cloud/serializers/account_attrs.py:150
|
||||||
|
@ -3834,21 +3833,21 @@ msgstr "请在 {} 秒后发送"
|
||||||
msgid "Children"
|
msgid "Children"
|
||||||
msgstr "节点"
|
msgstr "节点"
|
||||||
|
|
||||||
#: common/serializers/fields.py:135
|
#: common/serializers/fields.py:134
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Invalid pk \"{pk_value}\" - object does not exist."
|
msgid "Invalid pk \"{pk_value}\" - object does not exist."
|
||||||
msgstr "错误的 pk \"{pk_value}\" - 对象不存在"
|
msgstr "错误的 pk \"{pk_value}\" - 对象不存在"
|
||||||
|
|
||||||
#: common/serializers/fields.py:136
|
#: common/serializers/fields.py:135
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Incorrect type. Expected pk value, received {data_type}."
|
msgid "Incorrect type. Expected pk value, received {data_type}."
|
||||||
msgstr "错误类型。期望 pk 值,收到 {data_type}。"
|
msgstr "错误类型。期望 pk 值,收到 {data_type}。"
|
||||||
|
|
||||||
#: common/serializers/fields.py:210
|
#: common/serializers/fields.py:209
|
||||||
msgid "Invalid data type, should be list"
|
msgid "Invalid data type, should be list"
|
||||||
msgstr "错误的数据类型,应该是列表"
|
msgstr "错误的数据类型,应该是列表"
|
||||||
|
|
||||||
#: common/serializers/fields.py:225
|
#: common/serializers/fields.py:224
|
||||||
msgid "Invalid choice: {}"
|
msgid "Invalid choice: {}"
|
||||||
msgstr "无效选项: {}"
|
msgstr "无效选项: {}"
|
||||||
|
|
||||||
|
@ -4762,7 +4761,7 @@ msgid "My assets"
|
||||||
msgstr "我的资产"
|
msgstr "我的资产"
|
||||||
|
|
||||||
#: rbac/tree.py:58 terminal/models/applet/applet.py:52
|
#: rbac/tree.py:58 terminal/models/applet/applet.py:52
|
||||||
#: terminal/models/applet/applet.py:316 terminal/models/applet/host.py:30
|
#: terminal/models/applet/applet.py:317 terminal/models/applet/host.py:30
|
||||||
#: terminal/serializers/applet.py:15
|
#: terminal/serializers/applet.py:15
|
||||||
msgid "Applet"
|
msgid "Applet"
|
||||||
msgstr "远程应用"
|
msgstr "远程应用"
|
||||||
|
@ -5464,7 +5463,7 @@ msgstr "启用 Vault"
|
||||||
|
|
||||||
#: settings/serializers/feature.py:55
|
#: settings/serializers/feature.py:55
|
||||||
msgid "Mount Point"
|
msgid "Mount Point"
|
||||||
msgstr "挂在点"
|
msgstr "挂载点"
|
||||||
|
|
||||||
#: settings/serializers/feature.py:60
|
#: settings/serializers/feature.py:60
|
||||||
msgid "Chat AI"
|
msgid "Chat AI"
|
||||||
|
@ -6504,7 +6503,7 @@ msgstr "只支持自定义平台"
|
||||||
msgid "Missing type in platform.yml"
|
msgid "Missing type in platform.yml"
|
||||||
msgstr "在 platform.yml 中缺少类型"
|
msgstr "在 platform.yml 中缺少类型"
|
||||||
|
|
||||||
#: terminal/models/applet/applet.py:318 terminal/models/applet/host.py:36
|
#: terminal/models/applet/applet.py:319 terminal/models/applet/host.py:36
|
||||||
#: terminal/models/applet/host.py:138
|
#: terminal/models/applet/host.py:138
|
||||||
msgid "Hosting"
|
msgid "Hosting"
|
||||||
msgstr "宿主机"
|
msgstr "宿主机"
|
||||||
|
|
|
@ -26,6 +26,7 @@ def common_argument_spec():
|
||||||
|
|
||||||
|
|
||||||
class SSHClient:
|
class SSHClient:
|
||||||
|
TIMEOUT = 20
|
||||||
SLEEP_INTERVAL = 2
|
SLEEP_INTERVAL = 2
|
||||||
COMPLETE_FLAG = 'complete'
|
COMPLETE_FLAG = 'complete'
|
||||||
|
|
||||||
|
@ -170,7 +171,12 @@ class SSHClient:
|
||||||
time.sleep(self.SLEEP_INTERVAL)
|
time.sleep(self.SLEEP_INTERVAL)
|
||||||
output += self._get_recv()
|
output += self._get_recv()
|
||||||
continue
|
continue
|
||||||
|
start_time = time.time()
|
||||||
while self.COMPLETE_FLAG not in output:
|
while self.COMPLETE_FLAG not in output:
|
||||||
|
if time.time() - start_time > self.TIMEOUT:
|
||||||
|
error_msg = output
|
||||||
|
print("切换用户操作超时,跳出循环。")
|
||||||
|
break
|
||||||
time.sleep(self.SLEEP_INTERVAL)
|
time.sleep(self.SLEEP_INTERVAL)
|
||||||
received_output = self._get_recv().replace(f'"{self.COMPLETE_FLAG}"', '')
|
received_output = self._get_recv().replace(f'"{self.COMPLETE_FLAG}"', '')
|
||||||
output += received_output
|
output += received_output
|
||||||
|
|
|
@ -217,6 +217,7 @@ class JobExecutionTaskDetail(APIView):
|
||||||
'is_success': execution.is_success,
|
'is_success': execution.is_success,
|
||||||
'time_cost': execution.time_cost,
|
'time_cost': execution.time_cost,
|
||||||
'job_id': execution.job.id,
|
'job_id': execution.job.id,
|
||||||
|
'summary': execution.summary
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ from assets.const import Category, AllTypes
|
||||||
from assets.models import Node, Asset, Platform
|
from assets.models import Node, Asset, Platform
|
||||||
from assets.serializers.asset.common import AssetLabelSerializer, AssetProtocolsPermsSerializer
|
from assets.serializers.asset.common import AssetLabelSerializer, AssetProtocolsPermsSerializer
|
||||||
from common.serializers.fields import ObjectRelatedField, LabeledChoiceField
|
from common.serializers.fields import ObjectRelatedField, LabeledChoiceField
|
||||||
|
from common.serializers import ResourceLabelsMixin
|
||||||
from orgs.mixins.serializers import OrgResourceModelSerializerMixin
|
from orgs.mixins.serializers import OrgResourceModelSerializerMixin
|
||||||
from perms.serializers.permission import ActionChoicesField
|
from perms.serializers.permission import ActionChoicesField
|
||||||
|
|
||||||
|
@ -19,12 +20,11 @@ __all__ = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class AssetPermedSerializer(OrgResourceModelSerializerMixin):
|
class AssetPermedSerializer(OrgResourceModelSerializerMixin, ResourceLabelsMixin):
|
||||||
""" 被授权资产的数据结构 """
|
""" 被授权资产的数据结构 """
|
||||||
platform = ObjectRelatedField(required=False, queryset=Platform.objects, label=_('Platform'))
|
platform = ObjectRelatedField(required=False, queryset=Platform.objects, label=_('Platform'))
|
||||||
category = LabeledChoiceField(choices=Category.choices, read_only=True, label=_('Category'))
|
category = LabeledChoiceField(choices=Category.choices, read_only=True, label=_('Category'))
|
||||||
type = LabeledChoiceField(choices=AllTypes.choices(), read_only=True, label=_('Type'))
|
type = LabeledChoiceField(choices=AllTypes.choices(), read_only=True, label=_('Type'))
|
||||||
labels = AssetLabelSerializer(many=True, required=False, label=_('Label'))
|
|
||||||
domain = ObjectRelatedField(required=False, queryset=Node.objects, label=_('Domain'))
|
domain = ObjectRelatedField(required=False, queryset=Node.objects, label=_('Domain'))
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -30,6 +30,7 @@ exclude_permissions = (
|
||||||
('users', 'userpasswordhistory', '*', '*'),
|
('users', 'userpasswordhistory', '*', '*'),
|
||||||
('users', 'usersession', '*', '*'),
|
('users', 'usersession', '*', '*'),
|
||||||
('assets', 'adminuser', '*', '*'),
|
('assets', 'adminuser', '*', '*'),
|
||||||
|
('assets', 'label', '*', '*'),
|
||||||
('assets', 'assetgroup', '*', '*'),
|
('assets', 'assetgroup', '*', '*'),
|
||||||
('assets', 'cluster', '*', '*'),
|
('assets', 'cluster', '*', '*'),
|
||||||
('assets', 'systemuser', '*', '*'),
|
('assets', 'systemuser', '*', '*'),
|
||||||
|
|
|
@ -7,14 +7,14 @@ from ..models import Permission
|
||||||
__all__ = ['PermissionSerializer', 'UserPermsSerializer']
|
__all__ = ['PermissionSerializer', 'UserPermsSerializer']
|
||||||
|
|
||||||
|
|
||||||
class ContentTypeSerializer(serializers.ModelSerializer):
|
class PermissionContentTypeSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ContentType
|
model = ContentType
|
||||||
fields = ['id', 'app_label', 'model']
|
fields = ['id', 'app_label', 'model']
|
||||||
|
|
||||||
|
|
||||||
class PermissionSerializer(serializers.ModelSerializer):
|
class PermissionSerializer(serializers.ModelSerializer):
|
||||||
content_type = ContentTypeSerializer(read_only=True)
|
content_type = PermissionContentTypeSerializer(read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Permission
|
model = Permission
|
||||||
|
|
|
@ -86,7 +86,7 @@ class ChatAISettingSerializer(serializers.Serializer):
|
||||||
return
|
return
|
||||||
gpt_api_model = Protocol.gpt_protocols()[Protocol.chatgpt]['setting']['api_mode']
|
gpt_api_model = Protocol.gpt_protocols()[Protocol.chatgpt]['setting']['api_mode']
|
||||||
choices = gpt_api_model['choices']
|
choices = gpt_api_model['choices']
|
||||||
field_gpt_model._choices = choices
|
field_gpt_model.choices = choices
|
||||||
field_gpt_model.default = gpt_api_model['default']
|
field_gpt_model.default = gpt_api_model['default']
|
||||||
cls = self.__class__
|
cls = self.__class__
|
||||||
if cls.GPT_MODEL_CHOICES:
|
if cls.GPT_MODEL_CHOICES:
|
||||||
|
|
|
@ -172,8 +172,9 @@ class Applet(JMSBaseModel):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
spec_label = asset.labels.filter(label__name__in=['AppletHost', '发布机']).first()
|
spec_label = asset.labels.filter(label__name__in=['AppletHost', '发布机']).first()
|
||||||
if spec_label:
|
if spec_label and spec_label.label:
|
||||||
matched = [host for host in hosts if host.name == spec_label.value]
|
label_value = spec_label.label.value
|
||||||
|
matched = [host for host in hosts if host.name == label_value]
|
||||||
if matched:
|
if matched:
|
||||||
return matched[0]
|
return matched[0]
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,10 @@ class UserUserGroupRelationViewSet(JMSBulkRelationModelViewSet):
|
||||||
search_fields = filterset_fields
|
search_fields = filterset_fields
|
||||||
serializer_class = serializers.User2GroupRelationSerializer
|
serializer_class = serializers.User2GroupRelationSerializer
|
||||||
m2m_field = User.groups.field
|
m2m_field = User.groups.field
|
||||||
|
rbac_perms = {
|
||||||
|
'create': 'users.change_usergroup',
|
||||||
|
'bulk_destroy': 'users.change_usergroup',
|
||||||
|
}
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
return super().get_queryset().annotate(
|
return super().get_queryset().annotate(
|
||||||
|
|
|
@ -867,6 +867,7 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, LabeledMixin, JSONFilterM
|
||||||
queryset = cls.objects.all()
|
queryset = cls.objects.all()
|
||||||
if not current_org.is_root():
|
if not current_org.is_root():
|
||||||
queryset = current_org.get_members()
|
queryset = current_org.get_members()
|
||||||
|
queryset = queryset.exclude(is_service_account=True)
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -16,7 +16,8 @@ __all__ = [
|
||||||
|
|
||||||
class UserGroupSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer):
|
class UserGroupSerializer(ResourceLabelsMixin, BulkOrgResourceModelSerializer):
|
||||||
users = ObjectRelatedField(
|
users = ObjectRelatedField(
|
||||||
required=False, many=True, queryset=User.objects, label=_('User'),
|
required=False, many=True, queryset=User.objects,
|
||||||
|
attrs=("id", "name", "is_service_account"), label=_('User'),
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
|
@ -7540,6 +7540,22 @@ type = "legacy"
|
||||||
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
|
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
|
||||||
reference = "tsinghua"
|
reference = "tsinghua"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xlsxwriter"
|
||||||
|
version = "3.1.9"
|
||||||
|
description = "A Python module for creating Excel XLSX files."
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.6"
|
||||||
|
files = [
|
||||||
|
{file = "XlsxWriter-3.1.9-py3-none-any.whl", hash = "sha256:b61c1a0c786f82644936c0936ec96ee96cd3afb9440094232f7faef9b38689f0"},
|
||||||
|
{file = "XlsxWriter-3.1.9.tar.gz", hash = "sha256:de810bf328c6a4550f4ffd6b0b34972aeb7ffcf40f3d285a0413734f9b63a929"},
|
||||||
|
]
|
||||||
|
|
||||||
|
[package.source]
|
||||||
|
type = "legacy"
|
||||||
|
url = "https://pypi.tuna.tsinghua.edu.cn/simple"
|
||||||
|
reference = "tsinghua"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xmlsec"
|
name = "xmlsec"
|
||||||
version = "1.3.13"
|
version = "1.3.13"
|
||||||
|
@ -7755,4 +7771,4 @@ reference = "tsinghua"
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.11"
|
python-versions = "^3.11"
|
||||||
content-hash = "397cb294c81da3ce74f1a1c3044bd778669284c0c280177162ed9d51e623a7c8"
|
content-hash = "19950a5300f8a4425e3e3c9a096fc3782cb544e02152e92ac1bc09d1d9b5274a"
|
||||||
|
|
|
@ -145,6 +145,7 @@ user-agents = "^2.2.0"
|
||||||
django-cors-headers = "^4.3.0"
|
django-cors-headers = "^4.3.0"
|
||||||
mistune = "0.8.4"
|
mistune = "0.8.4"
|
||||||
openai = "^1.3.7"
|
openai = "^1.3.7"
|
||||||
|
xlsxwriter = "^3.1.9"
|
||||||
|
|
||||||
|
|
||||||
[tool.poetry.group.xpack.dependencies]
|
[tool.poetry.group.xpack.dependencies]
|
||||||
|
|
Loading…
Reference in New Issue