Compare commits

...

22 Commits
v3.0.2 ... v3.0

Author SHA1 Message Date
Bai
98a5e97518 fix: 修复日志记录到syslog时中文编码问题 2023-03-15 19:45:16 +08:00
ibuler
17be132497 fix: windows 平台默认不开启 console 2023-03-15 19:00:52 +08:00
feng
0cbce5f07a fix: 账号模版创建带密码的密钥之后无法添加到主机 2023-03-14 11:24:44 +08:00
ibuler
26dfb729bc perf: 优化资产迁移,避免冲突 2023-03-14 11:20:29 +08:00
fit2bot
bbe03ddb73 perf: 修改 ssh key with pass 报错 (#9918)
Co-authored-by: ibuler <ibuler@qq.com>
2023-03-10 16:05:11 +08:00
Bai
c88645fa57 feat: 支持飞书国际版(lark) 2023-03-10 15:48:08 +08:00
Bai
7271feb598 fix: ignore 2023-03-09 18:12:22 +08:00
jiangweidong
950183ca85 fix: 操作日志可能保存明文密码 2023-03-09 12:38:40 +08:00
Eric
6b1aa752d6 fix: 修复存储故障造成的录像获取失败问题 2023-03-09 11:51:37 +08:00
Bai
c908b47ccf fix: 修复组织管理员查看活动日志详情时没有对象的问题 2023-03-08 15:58:05 +08:00
Bai
88af33b7c2 fix: 修复组织管理员查看操作日志可以看到 system 组织下的操作问题, 只有系统管理员可以查看任务监控 2023-03-08 15:22:27 +08:00
老广
136537fcfb Merge pull request #9872 from jumpserver/pr@v3.0@fix_su_from_accounts
fix: 修复su-from-accounts API 500问题,Unsubscribe msg error 转成debug
2023-03-08 14:06:36 +08:00
老广
dfd404c549 Merge pull request #9875 from jumpserver/pr@v3.0@fix_operatelog_hide_sth
fix: 操作日志显示用户加密后的密文,及日期格式调整
2023-03-08 14:05:47 +08:00
老广
53886a5abf Merge pull request #9882 from jumpserver/pr@v3.0@perf_email_test_error
perf: 邮箱测试时,不填写'主题前缀'会报错
2023-03-08 14:02:58 +08:00
jiangweidong
50d3125fec perf: 邮箱测试时,不填写'主题前缀'会报错 2023-03-08 13:51:40 +08:00
jiangweidong
1145305f11 fix: 操作日志显示用户加密后的密文,及日期格式调整 2023-03-08 11:24:56 +08:00
feng
433f063142 fix: 修复su-from-accounts API 500问题,Unsubscribe msg error 转成debug 2023-03-08 11:02:05 +08:00
fit2bot
8c4e496391 fix: 修复i8n 500 (#9848)
Co-authored-by: feng <1304903146@qq.com>
2023-03-02 16:23:02 +08:00
Bai
fad214ccbb fix: 修复 ldap 用户登录时邮箱存在 500 的问题 2023-03-02 16:22:24 +08:00
Bai
3b0f68c4c7 fix: 修复 ldap 用户登录时邮箱存在 500 的问题 2023-03-02 16:11:04 +08:00
Aaron3S
87b4ecfb3a fix: 修复作业执行没有日志权限的问题 2023-03-01 18:34:55 +08:00
Bai
32f2be2793 fix: 资产类型树返回类型节点时, 没有platfrom设置isParent为False, 解决展开节点重复的问题 2023-03-01 17:28:59 +08:00
34 changed files with 252 additions and 174 deletions

View File

@@ -43,7 +43,7 @@ class AccountViewSet(OrgBulkModelViewSet):
asset = get_object_or_404(Asset, pk=asset_id)
accounts = asset.accounts.all()
else:
accounts = []
accounts = Account.objects.none()
accounts = self.filter_queryset(accounts)
serializer = serializers.AccountSerializer(accounts, many=True)
return Response(data=serializer.data)

View File

@@ -33,7 +33,8 @@ class AuthValidateMixin(serializers.Serializer):
return secret
elif secret_type == SecretType.SSH_KEY:
passphrase = passphrase if passphrase else None
return validate_ssh_key(secret, passphrase)
secret = validate_ssh_key(secret, passphrase)
return secret
else:
return secret
@@ -41,8 +42,9 @@ class AuthValidateMixin(serializers.Serializer):
secret_type = validated_data.get('secret_type')
passphrase = validated_data.get('passphrase')
secret = validated_data.pop('secret', None)
self.handle_secret(secret, secret_type, passphrase)
validated_data['secret'] = secret
validated_data['secret'] = self.handle_secret(
secret, secret_type, passphrase
)
for field in ('secret',):
value = validated_data.get(field)
if not value:

View File

@@ -39,7 +39,7 @@ class Protocol(ChoicesMixin, models.TextChoices):
'port': 3389,
'secret_types': ['password'],
'setting': {
'console': True,
'console': False,
'security': 'any',
}
},

View File

@@ -214,10 +214,13 @@ class AllTypes(ChoicesMixin):
tp_node = cls.choice_to_node(tp, category_node['id'], opened=False, meta=meta)
tp_count = category_type_mapper.get(category + '_' + tp, 0)
tp_node['name'] += f'({tp_count})'
platforms = tp_platforms.get(category + '_' + tp, [])
if not platforms:
tp_node['isParent'] = False
nodes.append(tp_node)
# Platform 格式化
for p in tp_platforms.get(category + '_' + tp, []):
for p in platforms:
platform_node = cls.platform_to_node(p, tp_node['id'], include_asset)
platform_node['name'] += f'({platform_count.get(p.id, 0)})'
nodes.append(platform_node)

View File

@@ -34,8 +34,9 @@ def migrate_database_to_asset(apps, *args):
_attrs = app.attrs or {}
attrs.update(_attrs)
name = 'DB-{}'.format(app.name)
db = db_model(
id=app.id, name=app.name, address=attrs['host'],
id=app.id, name=name, address=attrs['host'],
protocols='{}/{}'.format(app.type, attrs['port']),
db_name=attrs['database'] or '',
platform=platforms_map[app.type],
@@ -61,8 +62,9 @@ def migrate_cloud_to_asset(apps, *args):
for app in applications:
attrs = app.attrs
print("\t- Create cloud: {}".format(app.name))
name = 'Cloud-{}'.format(app.name)
cloud = cloud_model(
id=app.id, name=app.name,
id=app.id, name=name,
address=attrs.get('cluster', ''),
protocols='k8s/443', platform=platform,
org_id=app.org_id,

View File

@@ -0,0 +1,29 @@
# Generated by Django 3.2.17 on 2023-03-15 09:41
from django.db import migrations
def set_windows_platform_non_console(apps, schema_editor):
Platform = apps.get_model('assets', 'Platform')
names = ['Windows', 'Windows-RDP', 'Windows-TLS', 'RemoteAppHost']
windows = Platform.objects.filter(name__in=names)
if not windows:
return
for p in windows:
rdp = p.protocols.filter(name='rdp').first()
if not rdp:
continue
rdp.setting['console'] = False
rdp.save()
class Migration(migrations.Migration):
dependencies = [
('assets', '0109_alter_asset_options'),
]
operations = [
migrations.RunPython(set_windows_platform_non_console)
]

View File

@@ -11,7 +11,7 @@ __all__ = ['Platform', 'PlatformProtocol', 'PlatformAutomation']
class PlatformProtocol(models.Model):
SETTING_ATTRS = {
'console': True,
'console': False,
'security': 'any,tls,rdp',
'sftp_enabled': True,
'sftp_home': '/tmp'

View File

@@ -73,7 +73,7 @@ class AssetAccountSerializer(
'is_active', 'version', 'secret_type',
]
fields_write_only = [
'secret', 'push_now', 'template'
'secret', 'passphrase', 'push_now', 'template'
]
fields = fields_mini + fields_write_only
extra_kwargs = {

View File

@@ -1,6 +1,5 @@
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from django.core import validators
from assets.const.web import FillType
from common.serializers import WritableNestedModelSerializer
@@ -19,7 +18,7 @@ class ProtocolSettingSerializer(serializers.Serializer):
("nla", "NLA"),
]
# RDP
console = serializers.BooleanField(required=False)
console = serializers.BooleanField(required=False, default=False)
security = serializers.ChoiceField(choices=SECURITY_CHOICES, default="any")
# SFTP

View File

@@ -10,6 +10,7 @@ from rest_framework.permissions import IsAuthenticated
from common.drf.filters import DatetimeRangeFilter
from common.plugins.es import QuerySet as ESQuerySet
from common.utils import is_uuid
from common.utils import lazyproperty
from orgs.mixins.api import OrgReadonlyModelViewSet, OrgModelViewSet
from orgs.utils import current_org, tmp_to_root_org
from orgs.models import Organization
@@ -143,13 +144,19 @@ class OperateLogViewSet(OrgReadonlyModelViewSet):
search_fields = ['resource', 'user']
ordering = ['-datetime']
@lazyproperty
def is_action_detail(self):
return self.detail and self.request.query_params.get('type') == 'action_detail'
def get_serializer_class(self):
if self.request.query_params.get('type') == 'action_detail':
if self.is_action_detail:
return OperateLogActionDetailSerializer
return super().get_serializer_class()
def get_queryset(self):
org_q = Q(org_id=Organization.SYSTEM_ID) | Q(org_id=current_org.id)
org_q = Q(org_id=current_org.id)
if self.is_action_detail:
org_q |= Q(org_id=Organization.SYSTEM_ID)
with tmp_to_root_org():
qs = OperateLog.objects.filter(org_q)
es_config = settings.OPERATE_LOG_ELASTICSEARCH_CONFIG

View File

@@ -4,7 +4,6 @@ from django.db import transaction
from django.core.cache import cache
from django.utils.translation import ugettext_lazy as _
from users.models import User
from common.utils import get_request_ip, get_logger
from common.utils.timezone import as_current_tz
from common.utils.encode import Singleton

View File

@@ -2,7 +2,7 @@
#
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from audits.backends.db import OperateLogStore
from common.serializers.fields import LabeledChoiceField
from common.utils import reverse, i18n_trans
@@ -78,7 +78,7 @@ class OperateLogActionDetailSerializer(serializers.ModelSerializer):
return data
class OperateLogSerializer(serializers.ModelSerializer):
class OperateLogSerializer(BulkOrgResourceModelSerializer):
action = LabeledChoiceField(choices=ActionChoices.choices, label=_("Action"))
resource = serializers.SerializerMethodField(label=_("Resource"))
resource_type = serializers.SerializerMethodField(label=_('Resource Type'))

View File

@@ -1,13 +1,15 @@
import codecs
import copy
import csv
from itertools import chain
from datetime import datetime
from django.db import models
from django.http import HttpResponse
from common.utils.timezone import as_current_tz
from common.utils import validate_ip, get_ip_city, get_logger
from settings.serializers import SettingsSerializer
from .const import DEFAULT_CITY
logger = get_logger(__name__)
@@ -70,6 +72,8 @@ def _get_instance_field_value(
f.verbose_name = 'id'
elif isinstance(value, (list, dict)):
value = copy.deepcopy(value)
elif isinstance(value, datetime):
value = as_current_tz(value).strftime('%Y-%m-%d %H:%M:%S')
elif isinstance(f, models.OneToOneField) and isinstance(value, models.Model):
nested_data = _get_instance_field_value(
value, include_model_fields, model_need_continue_fields, ('id',)

View File

@@ -60,7 +60,7 @@ class FeiShuQRMixin(UserConfirmRequiredExceptionMixin, PermissionsMixin, View):
'state': state,
'redirect_uri': redirect_uri,
}
url = URL.AUTHEN + '?' + urlencode(params)
url = URL().authen + '?' + urlencode(params)
return url
@staticmethod

View File

@@ -6,6 +6,7 @@ import os
import datetime
from typing import Callable
from django.db import IntegrityError
from django.templatetags.static import static
from django.contrib.auth import login as auth_login, logout as auth_logout
from django.http import HttpResponse, HttpRequest
@@ -229,6 +230,23 @@ class UserLoginView(mixins.AuthMixin, UserLoginContextMixin, FormView):
) as e:
form.add_error('code', e.msg)
return super().form_invalid(form)
except (IntegrityError,) as e:
# (1062, "Duplicate entry 'youtester001@example.com' for key 'users_user.email'")
error = str(e)
if len(e.args) < 2:
form.add_error(None, error)
return super().form_invalid(form)
msg_list = e.args[1].split("'")
if len(msg_list) < 4:
form.add_error(None, error)
return super().form_invalid(form)
email, field = msg_list[1], msg_list[3]
if field == 'users_user.email':
error = _('User email already exists ({})').format(email)
form.add_error(None, error)
return super().form_invalid(form)
self.clear_rsa_key()
return self.redirect_to_guard_view()

View File

@@ -2,4 +2,3 @@ from __future__ import absolute_import
# This will make sure the app is always imported when
# Django starts so that shared_task will use this app.

View File

@@ -1,7 +1,10 @@
from werkzeug.local import Local
from django.utils import translation
thread_local = Local()
encrypted_field_set = set()
encrypted_field_set = {'password', 'secret'}
def _find(attr):
@@ -10,4 +13,5 @@ def _find(attr):
def add_encrypted_field_set(label):
if label:
encrypted_field_set.add(str(label))
with translation.override('en'):
encrypted_field_set.add(str(label))

View File

@@ -3,6 +3,7 @@ import json
from django.utils.translation import ugettext_lazy as _
from rest_framework.exceptions import APIException
from django.conf import settings
from common.utils.common import get_logger
from common.sdk.im.utils import digest
from common.sdk.im.mixin import RequestMixin, BaseRequest
@@ -11,14 +12,30 @@ logger = get_logger(__name__)
class URL:
AUTHEN = 'https://open.feishu.cn/open-apis/authen/v1/index'
GET_TOKEN = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/'
# https://open.feishu.cn/document/ukTMukTMukTM/uEDO4UjLxgDO14SM4gTN
GET_USER_INFO_BY_CODE = 'https://open.feishu.cn/open-apis/authen/v1/access_token'
@property
def host(self):
if settings.FEISHU_VERSION == 'feishu':
h = 'https://open.feishu.cn'
else:
h = 'https://open.larksuite.com'
return h
SEND_MESSAGE = 'https://open.feishu.cn/open-apis/im/v1/messages'
@property
def authen(self):
return f'{self.host}/open-apis/authen/v1/index'
@property
def get_token(self):
return f'{self.host}/open-apis/auth/v3/tenant_access_token/internal/'
@property
def get_user_info_by_code(self):
return f'{self.host}/open-apis/authen/v1/access_token'
@property
def send_message(self):
return f'{self.host}/open-apis/im/v1/messages'
class ErrorCode:
@@ -51,7 +68,7 @@ class FeishuRequests(BaseRequest):
def request_access_token(self):
data = {'app_id': self._app_id, 'app_secret': self._app_secret}
response = self.raw_request('post', url=URL.GET_TOKEN, data=data)
response = self.raw_request('post', url=URL().get_token, data=data)
self.check_errcode_is_0(response)
access_token = response['tenant_access_token']
@@ -86,7 +103,7 @@ class FeiShu(RequestMixin):
'code': code
}
data = self._requests.post(URL.GET_USER_INFO_BY_CODE, json=body, check_errcode_is_0=False)
data = self._requests.post(URL().get_user_info_by_code, json=body, check_errcode_is_0=False)
self._requests.check_errcode_is_0(data)
return data['data']['user_id']
@@ -107,7 +124,7 @@ class FeiShu(RequestMixin):
try:
logger.info(f'Feishu send text: user_ids={user_ids} msg={msg}')
self._requests.post(URL.SEND_MESSAGE, params=params, json=body)
self._requests.post(URL().send_message, params=params, json=body)
except APIException as e:
# 只处理可预知的错误
logger.exception(e)

View File

@@ -108,7 +108,7 @@ class Subscription:
try:
self.sub.close()
except Exception as e:
logger.error('Unsubscribe msg error: {}'.format(e))
logger.debug('Unsubscribe msg error: {}'.format(e))
def retry(self, _next, error, complete):
logger.info('Retry subscribe channel: {}'.format(self.ch))

View File

@@ -274,4 +274,4 @@ def ensure_last_char_is_ascii(data):
def data_to_json(data, sort_keys=True, indent=2, cls=None):
if cls is None:
cls = DjangoJSONEncoder
return json.dumps(data, sort_keys=sort_keys, indent=indent, cls=cls)
return json.dumps(data, ensure_ascii=False, sort_keys=sort_keys, indent=indent, cls=cls)

View File

@@ -35,7 +35,10 @@ def i18n_trans(s):
tpl, args = s.split(' % ', 1)
args = args.split(', ')
args = [gettext(arg) for arg in args]
return gettext(tpl) % tuple(args)
try:
return gettext(tpl) % tuple(args)
except TypeError:
return gettext(tpl)
def hello():

View File

@@ -376,6 +376,7 @@ class Config(dict):
'AUTH_FEISHU': False,
'FEISHU_APP_ID': '',
'FEISHU_APP_SECRET': '',
'FEISHU_VERSION': 'feishu',
'LOGIN_REDIRECT_TO_BACKEND': '', # 'OPENID / CAS / SAML2
'LOGIN_REDIRECT_MSG_ENABLED': True,

View File

@@ -137,6 +137,7 @@ DINGTALK_APPSECRET = CONFIG.DINGTALK_APPSECRET
AUTH_FEISHU = CONFIG.AUTH_FEISHU
FEISHU_APP_ID = CONFIG.FEISHU_APP_ID
FEISHU_APP_SECRET = CONFIG.FEISHU_APP_SECRET
FEISHU_VERSION = CONFIG.FEISHU_VERSION
# Saml2 auth
AUTH_SAML2 = CONFIG.AUTH_SAML2

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-02-23 19:11+0800\n"
"POT-Creation-Date: 2023-03-02 16:00+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"
@@ -394,7 +394,7 @@ msgid "Date last login"
msgstr "最終ログイン日"
#: accounts/models/automations/gather_account.py:15
#: accounts/models/automations/push_account.py:13 accounts/models/base.py:34
#: accounts/models/automations/push_account.py:14 accounts/models/base.py:34
#: acls/serializers/base.py:18 acls/serializers/base.py:49
#: assets/models/_user.py:23 audits/models.py:157 authentication/forms.py:25
#: authentication/forms.py:27 authentication/models/temp_token.py:9
@@ -419,11 +419,11 @@ msgstr "自動収集アカウント"
msgid "Gather asset accounts"
msgstr "アカウントのコレクション"
#: accounts/models/automations/push_account.py:12
#: accounts/models/automations/push_account.py:13
msgid "Triggers"
msgstr "トリガー方式"
#: accounts/models/automations/push_account.py:14 acls/models/base.py:81
#: accounts/models/automations/push_account.py:15 acls/models/base.py:81
#: acls/serializers/base.py:81 acls/serializers/login_acl.py:25
#: assets/models/cmd_filter.py:81 audits/models.py:65 audits/serializers.py:82
#: authentication/serializers/connect_token_secret.py:109
@@ -431,7 +431,7 @@ msgstr "トリガー方式"
msgid "Action"
msgstr "アクション"
#: accounts/models/automations/push_account.py:40
#: accounts/models/automations/push_account.py:43
msgid "Push asset account"
msgstr "アカウントプッシュ"
@@ -447,7 +447,7 @@ msgstr "アカウントの確認"
#: assets/models/group.py:20 assets/models/label.py:18
#: assets/models/platform.py:21 assets/models/platform.py:76
#: assets/serializers/asset/common.py:67 assets/serializers/asset/common.py:143
#: assets/serializers/platform.py:91 assets/serializers/platform.py:136
#: assets/serializers/platform.py:133
#: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:21
#: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57
#: ops/models/job.py:91 ops/models/playbook.py:23 ops/serializers/job.py:19
@@ -533,7 +533,7 @@ msgstr "エスクローされたパスワード"
#: accounts/serializers/account/account.py:75 applications/models.py:11
#: assets/models/label.py:21 assets/models/platform.py:77
#: assets/serializers/asset/common.py:120 assets/serializers/cagegory.py:8
#: assets/serializers/platform.py:97 assets/serializers/platform.py:137
#: assets/serializers/platform.py:94 assets/serializers/platform.py:134
#: perms/serializers/user_permission.py:26 settings/models.py:35
#: tickets/models/ticket/apply_application.py:13
msgid "Category"
@@ -544,7 +544,7 @@ msgstr "カテゴリ"
#: acls/serializers/command_acl.py:18 applications/models.py:14
#: assets/models/_user.py:50 assets/models/automations/base.py:20
#: assets/models/cmd_filter.py:74 assets/models/platform.py:78
#: assets/serializers/asset/common.py:121 assets/serializers/platform.py:96
#: assets/serializers/asset/common.py:121 assets/serializers/platform.py:93
#: audits/serializers.py:48
#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:102
#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:31
@@ -741,7 +741,7 @@ msgstr "アクティブ"
#: authentication/models/sso_token.py:16
#: notifications/models/notification.py:12
#: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58
#: perms/serializers/permission.py:23 rbac/builtin.py:118
#: perms/serializers/permission.py:23 rbac/builtin.py:122
#: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:19
#: terminal/models/session/session.py:30 terminal/models/session/sharing.py:32
#: terminal/notifications.py:96 terminal/notifications.py:144
@@ -908,7 +908,7 @@ msgstr "アプリケーション"
msgid "Can match application"
msgstr "アプリケーションを一致させることができます"
#: assets/api/asset/asset.py:142
#: assets/api/asset/asset.py:143
msgid "Cannot create asset directly, you should create a host or other"
msgstr ""
"資産を直接作成することはできません。ホストまたはその他を作成する必要がありま"
@@ -944,10 +944,8 @@ msgid "No account"
msgstr "アカウントなし"
#: assets/automations/ping_gateway/manager.py:36
#, fuzzy
#| msgid "Assets amount"
msgid "Asset, {}, using account {}"
msgstr "資産"
msgstr "資産, {}, アカウントを使用 {}"
#: assets/automations/ping_gateway/manager.py:55
#, python-brace-format
@@ -1459,23 +1457,23 @@ msgstr "メタ"
msgid "Internal"
msgstr "ビルトイン"
#: assets/models/platform.py:83 assets/serializers/platform.py:94
#: assets/models/platform.py:83 assets/serializers/platform.py:91
msgid "Charset"
msgstr "シャーセット"
#: assets/models/platform.py:85 assets/serializers/platform.py:122
#: assets/models/platform.py:85 assets/serializers/platform.py:119
msgid "Domain enabled"
msgstr "ドメインを有効にする"
#: assets/models/platform.py:87 assets/serializers/platform.py:121
#: assets/models/platform.py:87 assets/serializers/platform.py:118
msgid "Su enabled"
msgstr "アカウントの切り替えを有効にする"
#: assets/models/platform.py:88 assets/serializers/platform.py:104
#: assets/models/platform.py:88 assets/serializers/platform.py:101
msgid "Su method"
msgstr "アカウントの切り替え方法"
#: assets/models/platform.py:90 assets/serializers/platform.py:101
#: assets/models/platform.py:90 assets/serializers/platform.py:98
msgid "Automation"
msgstr "オートメーション"
@@ -1488,7 +1486,7 @@ msgstr "%(value)s は偶数ではありません"
msgid "Auto fill"
msgstr "自動充填"
#: assets/serializers/asset/common.py:123 assets/serializers/platform.py:99
#: assets/serializers/asset/common.py:123 assets/serializers/platform.py:96
#: authentication/serializers/connect_token_secret.py:28
#: authentication/serializers/connect_token_secret.py:66
#: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:99
@@ -1629,7 +1627,7 @@ msgstr "アカウントの収集方法"
msgid "Primary"
msgstr "主要"
#: assets/serializers/platform.py:123
#: assets/serializers/platform.py:120
msgid "Default Domain"
msgstr "デフォルト ドメイン"
@@ -1940,20 +1938,20 @@ msgid "Auth Token"
msgstr "認証トークン"
#: audits/signal_handlers/login_log.py:31 authentication/notifications.py:73
#: authentication/views/login.py:73 authentication/views/wecom.py:177
#: authentication/views/login.py:74 authentication/views/wecom.py:177
#: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10
#: users/models/user.py:778
msgid "WeCom"
msgstr "企業微信"
#: audits/signal_handlers/login_log.py:32 authentication/views/feishu.py:144
#: authentication/views/login.py:85 notifications/backends/__init__.py:14
#: authentication/views/login.py:86 notifications/backends/__init__.py:14
#: settings/serializers/auth/feishu.py:10 users/models/user.py:780
msgid "FeiShu"
msgstr "本を飛ばす"
#: audits/signal_handlers/login_log.py:33 authentication/views/dingtalk.py:179
#: authentication/views/login.py:79 notifications/backends/__init__.py:12
#: authentication/views/login.py:80 notifications/backends/__init__.py:12
#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:779
msgid "DingTalk"
msgstr "DingTalk"
@@ -2237,15 +2235,15 @@ msgstr "本を飛ばすは拘束されていません"
msgid "Your password is invalid"
msgstr "パスワードが無効です"
#: authentication/errors/redirect.py:85 authentication/mixins.py:306
#: authentication/errors/redirect.py:85 authentication/mixins.py:307
msgid "Your password is too simple, please change it for security"
msgstr "パスワードがシンプルすぎるので、セキュリティのために変更してください"
#: authentication/errors/redirect.py:93 authentication/mixins.py:313
#: authentication/errors/redirect.py:93 authentication/mixins.py:314
msgid "You should to change your password before login"
msgstr "ログインする前にパスワードを変更する必要があります"
#: authentication/errors/redirect.py:101 authentication/mixins.py:320
#: authentication/errors/redirect.py:101 authentication/mixins.py:321
msgid "Your password has expired, please reset before logging in"
msgstr ""
"パスワードの有効期限が切れました。ログインする前にリセットしてください。"
@@ -2348,11 +2346,11 @@ msgstr "無効にする電話番号をクリアする"
msgid "Authentication failed (before login check failed): {}"
msgstr "認証に失敗しました (ログインチェックが失敗する前): {}"
#: authentication/mixins.py:256
#: authentication/mixins.py:257
msgid "The MFA type ({}) is not enabled"
msgstr "MFAタイプ ({}) が有効になっていない"
#: authentication/mixins.py:296
#: authentication/mixins.py:297
msgid "Please change your password"
msgstr "パスワードを変更してください"
@@ -2812,19 +2810,23 @@ msgstr "本を飛ばすからユーザーを取得できませんでした"
msgid "Please login with a password and then bind the FeiShu"
msgstr "パスワードでログインしてから本を飛ばすをバインドしてください"
#: authentication/views/login.py:181
#: authentication/views/login.py:182
msgid "Redirecting"
msgstr "リダイレクト"
#: authentication/views/login.py:182
#: authentication/views/login.py:183
msgid "Redirecting to {} authentication"
msgstr "{} 認証へのリダイレクト"
#: authentication/views/login.py:205
#: authentication/views/login.py:206
msgid "Please enable cookies and try again."
msgstr "クッキーを有効にして、もう一度お試しください。"
#: authentication/views/login.py:307
#: authentication/views/login.py:238
msgid "User email already exists ({})"
msgstr "ユーザー メールボックスは既に存在します ({})"
#: authentication/views/login.py:318
msgid ""
"Wait for <b>{}</b> confirm, You also can copy link to her/him <br/>\n"
" Don't close this page"
@@ -2832,15 +2834,15 @@ msgstr ""
"<b>{}</b> 確認を待ちます。彼女/彼へのリンクをコピーすることもできます <br/>\n"
" このページを閉じないでください"
#: authentication/views/login.py:312
#: authentication/views/login.py:323
msgid "No ticket found"
msgstr "チケットが見つかりません"
#: authentication/views/login.py:348
#: authentication/views/login.py:359
msgid "Logout success"
msgstr "ログアウト成功"
#: authentication/views/login.py:349
#: authentication/views/login.py:360
msgid "Logout success, return login page"
msgstr "ログアウト成功、ログインページを返す"
@@ -3509,15 +3511,15 @@ msgstr "終了しました"
msgid "Time cost"
msgstr "時を過ごす"
#: ops/tasks.py:32
#: ops/tasks.py:34
msgid "Run ansible task"
msgstr "Ansible タスクを実行する"
#: ops/tasks.py:61
#: ops/tasks.py:63
msgid "Run ansible task execution"
msgstr "Ansible タスクの実行を開始する"
#: ops/tasks.py:77
#: ops/tasks.py:79
msgid "Clear celery periodic tasks"
msgstr "タスクログを定期的にクリアする"
@@ -3735,7 +3737,7 @@ msgstr "内部の役割は、破壊することはできません"
msgid "The role has been bound to users, can't be destroy"
msgstr "ロールはユーザーにバインドされており、破壊することはできません"
#: rbac/api/role.py:83
#: rbac/api/role.py:87
msgid "Internal role, can't be update"
msgstr "内部ロール、更新できません"
@@ -3747,27 +3749,27 @@ msgstr "{} 少なくとも1つのシステムロール"
msgid "RBAC"
msgstr "RBAC"
#: rbac/builtin.py:109
#: rbac/builtin.py:113
msgid "SystemAdmin"
msgstr "システム管理者"
#: rbac/builtin.py:112
#: rbac/builtin.py:116
msgid "SystemAuditor"
msgstr "システム監査人"
#: rbac/builtin.py:115
#: rbac/builtin.py:119
msgid "SystemComponent"
msgstr "システムコンポーネント"
#: rbac/builtin.py:121
#: rbac/builtin.py:125
msgid "OrgAdmin"
msgstr "組織管理者"
#: rbac/builtin.py:124
#: rbac/builtin.py:128
msgid "OrgAuditor"
msgstr "監査員を組織する"
#: rbac/builtin.py:127
#: rbac/builtin.py:131
msgid "OrgUser"
msgstr "組織ユーザー"
@@ -5408,9 +5410,9 @@ msgstr "セッション"
msgid "Risk level"
msgstr "リスクレベル"
#: terminal/connect_methods.py:47 terminal/connect_methods.py:48
#: terminal/connect_methods.py:49 terminal/connect_methods.py:50
#: terminal/connect_methods.py:51
#: terminal/connect_methods.py:54 terminal/connect_methods.py:55
#: terminal/connect_methods.py:56 terminal/connect_methods.py:57
#: terminal/connect_methods.py:58
msgid "DB Client"
msgstr "データベース クライアント"
@@ -5899,11 +5901,11 @@ msgstr "孤立したセッションをクリアする"
msgid "Upload session replay to external storage"
msgstr "セッションの記録を外部ストレージにアップロードする"
#: terminal/tasks.py:83
#: terminal/tasks.py:84
msgid "Run applet host deployment"
msgstr "アプリケーション マシンの展開を実行する"
#: terminal/tasks.py:90
#: terminal/tasks.py:94
msgid "Install applet"
msgstr "アプリをインストールする"
@@ -7388,30 +7390,3 @@ msgstr "究極のエディション"
#: xpack/plugins/license/models.py:85
msgid "Community edition"
msgstr "コミュニティ版"
#, fuzzy
#~| msgid "Only admin users"
#~ msgid "Unix admin user"
#~ msgstr "管理者のみ"
#, fuzzy
#~| msgid "Only admin users"
#~ msgid "Windows admin user"
#~ msgstr "管理者のみ"
#, fuzzy
#~| msgid "Only admin users"
#~ msgid "Linux admin user"
#~ msgstr "管理者のみ"
#~ msgid "Can push account to asset"
#~ msgstr "アカウントをアセットにプッシュできます"
#~ msgid "Add asset to node"
#~ msgstr "ノードにアセットを追加する"
#~ msgid "Move asset to node"
#~ msgstr "アセットをノードに移動する"
#~ msgid "Remove asset from node"
#~ msgstr "ノードからアセットを削除"

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-02-23 19:11+0800\n"
"POT-Creation-Date: 2023-03-02 16:00+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"
@@ -393,7 +393,7 @@ msgid "Date last login"
msgstr "最后登录日期"
#: accounts/models/automations/gather_account.py:15
#: accounts/models/automations/push_account.py:13 accounts/models/base.py:34
#: accounts/models/automations/push_account.py:14 accounts/models/base.py:34
#: acls/serializers/base.py:18 acls/serializers/base.py:49
#: assets/models/_user.py:23 audits/models.py:157 authentication/forms.py:25
#: authentication/forms.py:27 authentication/models/temp_token.py:9
@@ -418,11 +418,11 @@ msgstr "自动化收集账号"
msgid "Gather asset accounts"
msgstr "收集账号"
#: accounts/models/automations/push_account.py:12
#: accounts/models/automations/push_account.py:13
msgid "Triggers"
msgstr "触发方式"
#: accounts/models/automations/push_account.py:14 acls/models/base.py:81
#: accounts/models/automations/push_account.py:15 acls/models/base.py:81
#: acls/serializers/base.py:81 acls/serializers/login_acl.py:25
#: assets/models/cmd_filter.py:81 audits/models.py:65 audits/serializers.py:82
#: authentication/serializers/connect_token_secret.py:109
@@ -430,7 +430,7 @@ msgstr "触发方式"
msgid "Action"
msgstr "动作"
#: accounts/models/automations/push_account.py:40
#: accounts/models/automations/push_account.py:43
msgid "Push asset account"
msgstr "账号推送"
@@ -446,7 +446,7 @@ msgstr "账号验证"
#: assets/models/group.py:20 assets/models/label.py:18
#: assets/models/platform.py:21 assets/models/platform.py:76
#: assets/serializers/asset/common.py:67 assets/serializers/asset/common.py:143
#: assets/serializers/platform.py:91 assets/serializers/platform.py:136
#: assets/serializers/platform.py:133
#: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:21
#: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57
#: ops/models/job.py:91 ops/models/playbook.py:23 ops/serializers/job.py:19
@@ -529,7 +529,7 @@ msgstr "已托管密码"
#: accounts/serializers/account/account.py:75 applications/models.py:11
#: assets/models/label.py:21 assets/models/platform.py:77
#: assets/serializers/asset/common.py:120 assets/serializers/cagegory.py:8
#: assets/serializers/platform.py:97 assets/serializers/platform.py:137
#: assets/serializers/platform.py:94 assets/serializers/platform.py:134
#: perms/serializers/user_permission.py:26 settings/models.py:35
#: tickets/models/ticket/apply_application.py:13
msgid "Category"
@@ -540,7 +540,7 @@ msgstr "类别"
#: acls/serializers/command_acl.py:18 applications/models.py:14
#: assets/models/_user.py:50 assets/models/automations/base.py:20
#: assets/models/cmd_filter.py:74 assets/models/platform.py:78
#: assets/serializers/asset/common.py:121 assets/serializers/platform.py:96
#: assets/serializers/asset/common.py:121 assets/serializers/platform.py:93
#: audits/serializers.py:48
#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:102
#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:31
@@ -737,7 +737,7 @@ msgstr "激活中"
#: authentication/models/sso_token.py:16
#: notifications/models/notification.py:12
#: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58
#: perms/serializers/permission.py:23 rbac/builtin.py:118
#: perms/serializers/permission.py:23 rbac/builtin.py:122
#: rbac/models/rolebinding.py:49 terminal/backends/command/models.py:19
#: terminal/models/session/session.py:30 terminal/models/session/sharing.py:32
#: terminal/notifications.py:96 terminal/notifications.py:144
@@ -902,7 +902,7 @@ msgstr "应用程序"
msgid "Can match application"
msgstr "匹配应用"
#: assets/api/asset/asset.py:142
#: assets/api/asset/asset.py:143
msgid "Cannot create asset directly, you should create a host or other"
msgstr "不能直接创建资产, 你应该创建主机或其他资产"
@@ -936,10 +936,8 @@ msgid "No account"
msgstr "没有账号"
#: assets/automations/ping_gateway/manager.py:36
#, fuzzy
#| msgid "Assets amount"
msgid "Asset, {}, using account {}"
msgstr "资产数量"
msgstr "资产, {}, 使用账号 {}"
#: assets/automations/ping_gateway/manager.py:55
#, python-brace-format
@@ -1451,23 +1449,23 @@ msgstr "元数据"
msgid "Internal"
msgstr "内置"
#: assets/models/platform.py:83 assets/serializers/platform.py:94
#: assets/models/platform.py:83 assets/serializers/platform.py:91
msgid "Charset"
msgstr "编码"
#: assets/models/platform.py:85 assets/serializers/platform.py:122
#: assets/models/platform.py:85 assets/serializers/platform.py:119
msgid "Domain enabled"
msgstr "启用网域"
#: assets/models/platform.py:87 assets/serializers/platform.py:121
#: assets/models/platform.py:87 assets/serializers/platform.py:118
msgid "Su enabled"
msgstr "启用账号切换"
#: assets/models/platform.py:88 assets/serializers/platform.py:104
#: assets/models/platform.py:88 assets/serializers/platform.py:101
msgid "Su method"
msgstr "账号切换方式"
#: assets/models/platform.py:90 assets/serializers/platform.py:101
#: assets/models/platform.py:90 assets/serializers/platform.py:98
msgid "Automation"
msgstr "自动化"
@@ -1480,7 +1478,7 @@ msgstr "%(value)s is not an even number"
msgid "Auto fill"
msgstr "自动代填"
#: assets/serializers/asset/common.py:123 assets/serializers/platform.py:99
#: assets/serializers/asset/common.py:123 assets/serializers/platform.py:96
#: authentication/serializers/connect_token_secret.py:28
#: authentication/serializers/connect_token_secret.py:66
#: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:99
@@ -1621,7 +1619,7 @@ msgstr "收集账号方式"
msgid "Primary"
msgstr "主要的"
#: assets/serializers/platform.py:123
#: assets/serializers/platform.py:120
msgid "Default Domain"
msgstr "默认网域"
@@ -1930,20 +1928,20 @@ msgid "Auth Token"
msgstr "认证令牌"
#: audits/signal_handlers/login_log.py:31 authentication/notifications.py:73
#: authentication/views/login.py:73 authentication/views/wecom.py:177
#: authentication/views/login.py:74 authentication/views/wecom.py:177
#: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10
#: users/models/user.py:778
msgid "WeCom"
msgstr "企业微信"
#: audits/signal_handlers/login_log.py:32 authentication/views/feishu.py:144
#: authentication/views/login.py:85 notifications/backends/__init__.py:14
#: authentication/views/login.py:86 notifications/backends/__init__.py:14
#: settings/serializers/auth/feishu.py:10 users/models/user.py:780
msgid "FeiShu"
msgstr "飞书"
#: audits/signal_handlers/login_log.py:33 authentication/views/dingtalk.py:179
#: authentication/views/login.py:79 notifications/backends/__init__.py:12
#: authentication/views/login.py:80 notifications/backends/__init__.py:12
#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:779
msgid "DingTalk"
msgstr "钉钉"
@@ -2217,15 +2215,15 @@ msgstr "没有绑定飞书"
msgid "Your password is invalid"
msgstr "您的密码无效"
#: authentication/errors/redirect.py:85 authentication/mixins.py:306
#: authentication/errors/redirect.py:85 authentication/mixins.py:307
msgid "Your password is too simple, please change it for security"
msgstr "你的密码过于简单,为了安全,请修改"
#: authentication/errors/redirect.py:93 authentication/mixins.py:313
#: authentication/errors/redirect.py:93 authentication/mixins.py:314
msgid "You should to change your password before login"
msgstr "登录完成前,请先修改密码"
#: authentication/errors/redirect.py:101 authentication/mixins.py:320
#: authentication/errors/redirect.py:101 authentication/mixins.py:321
msgid "Your password has expired, please reset before logging in"
msgstr "您的密码已过期,先修改再登录"
@@ -2326,11 +2324,11 @@ msgstr "清空手机号码禁用"
msgid "Authentication failed (before login check failed): {}"
msgstr "认证失败(登录前检查失败): {}"
#: authentication/mixins.py:256
#: authentication/mixins.py:257
msgid "The MFA type ({}) is not enabled"
msgstr "该 MFA ({}) 方式没有启用"
#: authentication/mixins.py:296
#: authentication/mixins.py:297
msgid "Please change your password"
msgstr "请修改密码"
@@ -2782,19 +2780,23 @@ msgstr "从飞书获取用户失败"
msgid "Please login with a password and then bind the FeiShu"
msgstr "请使用密码登录,然后绑定飞书"
#: authentication/views/login.py:181
#: authentication/views/login.py:182
msgid "Redirecting"
msgstr "跳转中"
#: authentication/views/login.py:182
#: authentication/views/login.py:183
msgid "Redirecting to {} authentication"
msgstr "正在跳转到 {} 认证"
#: authentication/views/login.py:205
#: authentication/views/login.py:206
msgid "Please enable cookies and try again."
msgstr "设置你的浏览器支持cookie"
#: authentication/views/login.py:307
#: authentication/views/login.py:238
msgid "User email already exists ({})"
msgstr "用户邮箱已存在 ({})"
#: authentication/views/login.py:318
msgid ""
"Wait for <b>{}</b> confirm, You also can copy link to her/him <br/>\n"
" Don't close this page"
@@ -2802,15 +2804,15 @@ msgstr ""
"等待 <b>{}</b> 确认, 你也可以复制链接发给他/她 <br/>\n"
" 不要关闭本页面"
#: authentication/views/login.py:312
#: authentication/views/login.py:323
msgid "No ticket found"
msgstr "没有发现工单"
#: authentication/views/login.py:348
#: authentication/views/login.py:359
msgid "Logout success"
msgstr "退出登录成功"
#: authentication/views/login.py:349
#: authentication/views/login.py:360
msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面"
@@ -3474,15 +3476,15 @@ msgstr "是否完成"
msgid "Time cost"
msgstr "花费时间"
#: ops/tasks.py:32
#: ops/tasks.py:34
msgid "Run ansible task"
msgstr "运行 Ansible 任务"
#: ops/tasks.py:61
#: ops/tasks.py:63
msgid "Run ansible task execution"
msgstr "开始执行 Ansible 任务"
#: ops/tasks.py:77
#: ops/tasks.py:79
msgid "Clear celery periodic tasks"
msgstr "清理周期任务"
@@ -3699,7 +3701,7 @@ msgstr "内部角色,不能删除"
msgid "The role has been bound to users, can't be destroy"
msgstr "角色已绑定用户,不能删除"
#: rbac/api/role.py:83
#: rbac/api/role.py:87
msgid "Internal role, can't be update"
msgstr "内部角色,不能更新"
@@ -3711,27 +3713,27 @@ msgstr "{} 至少有一个系统角色"
msgid "RBAC"
msgstr "RBAC"
#: rbac/builtin.py:109
#: rbac/builtin.py:113
msgid "SystemAdmin"
msgstr "系统管理员"
#: rbac/builtin.py:112
#: rbac/builtin.py:116
msgid "SystemAuditor"
msgstr "系统审计员"
#: rbac/builtin.py:115
#: rbac/builtin.py:119
msgid "SystemComponent"
msgstr "系统组件"
#: rbac/builtin.py:121
#: rbac/builtin.py:125
msgid "OrgAdmin"
msgstr "组织管理员"
#: rbac/builtin.py:124
#: rbac/builtin.py:128
msgid "OrgAuditor"
msgstr "组织审计员"
#: rbac/builtin.py:127
#: rbac/builtin.py:131
msgid "OrgUser"
msgstr "组织用户"
@@ -5336,9 +5338,9 @@ msgstr "会话"
msgid "Risk level"
msgstr "风险等级"
#: terminal/connect_methods.py:47 terminal/connect_methods.py:48
#: terminal/connect_methods.py:49 terminal/connect_methods.py:50
#: terminal/connect_methods.py:51
#: terminal/connect_methods.py:54 terminal/connect_methods.py:55
#: terminal/connect_methods.py:56 terminal/connect_methods.py:57
#: terminal/connect_methods.py:58
msgid "DB Client"
msgstr "数据库客户端"
@@ -5825,11 +5827,11 @@ msgstr "清除孤儿会话"
msgid "Upload session replay to external storage"
msgstr "上传会话录像到外部存储"
#: terminal/tasks.py:83
#: terminal/tasks.py:84
msgid "Run applet host deployment"
msgstr "运行应用机部署"
#: terminal/tasks.py:90
#: terminal/tasks.py:94
msgid "Install applet"
msgstr "安装应用"

View File

@@ -62,10 +62,10 @@ class PlaybookFileBrowserAPIView(APIView):
rbac_perms = ()
permission_classes = (RBACPermission,)
rbac_perms = {
'GET': 'ops.change_playbooks',
'POST': 'ops.change_playbooks',
'DELETE': 'ops.change_playbooks',
'PATCH': 'ops.change_playbooks',
'GET': 'ops.change_playbook',
'POST': 'ops.change_playbook',
'DELETE': 'ops.change_playbook',
'PATCH': 'ops.change_playbook',
}
protected_files = ['root', 'main.yml']

View File

@@ -13,7 +13,7 @@ class CeleryTaskLogView(PermissionsMixin, TemplateView):
template_name = 'ops/celery_task_log.html'
permission_classes = [RBACPermission]
rbac_perms = {
'GET': 'ops.view_celerytask'
'GET': 'ops.view_celerytaskexecution'
}
def get_context_data(self, **kwargs):

View File

@@ -23,6 +23,7 @@ def migrate_app_perms_to_assets(apps, schema_editor):
asset_permission = asset_permission_model()
for attr in attrs:
setattr(asset_permission, attr, getattr(app_perm, attr))
asset_permission.name = f"App-{app_perm.name}"
asset_permissions.append(asset_permission)
asset_permission_model.objects.bulk_create(asset_permissions, ignore_conflicts=True)

View File

@@ -9,11 +9,11 @@ def migrate_system_user_to_accounts(apps, schema_editor):
bulk_size = 10000
while True:
asset_permissions = asset_permission_model.objects \
.prefetch_related('system_users')[count:bulk_size]
.prefetch_related('system_users')[count:bulk_size]
if not asset_permissions:
break
count += len(asset_permissions)
count += len(asset_permissions)
updated = []
for asset_permission in asset_permissions:
asset_permission.accounts = [s.username for s in asset_permission.system_users.all()]

View File

@@ -22,6 +22,7 @@ user_perms = (
("ops", "playbook", "*", "*"),
("ops", "job", "*", "*"),
("ops", "jobexecution", "*", "*"),
("ops", "celerytaskexecution", "view", "*"),
)
system_user_perms = (

View File

@@ -135,7 +135,7 @@ only_system_permissions = (
('xpack', 'license', '*', '*'),
('settings', 'setting', '*', '*'),
('tickets', '*', '*', '*'),
('ops', 'task', 'view', 'taskmonitor'),
('ops', 'celerytask', 'view', 'taskmonitor'),
('terminal', 'terminal', '*', '*'),
('terminal', 'commandstorage', '*', '*'),
('terminal', 'replaystorage', '*', '*'),

View File

@@ -42,7 +42,7 @@ class MailTestingAPI(APIView):
# if k.startswith('EMAIL'):
# setattr(settings, k, v)
try:
subject = settings.EMAIL_SUBJECT_PREFIX + "Test"
subject = settings.EMAIL_SUBJECT_PREFIX or '' + "Test"
message = "Test smtp setting"
email_from = email_from or email_host_user
email_recipient = email_recipient or email_from

View File

@@ -9,6 +9,13 @@ __all__ = ['FeiShuSettingSerializer']
class FeiShuSettingSerializer(serializers.Serializer):
PREFIX_TITLE = _('FeiShu')
VERSION_CHOICES = (
('feishu', _('FeiShu')),
('lark', 'Lark')
)
AUTH_FEISHU = serializers.BooleanField(default=False, label=_('Enable FeiShu Auth'))
FEISHU_APP_ID = serializers.CharField(max_length=256, required=True, label='App ID')
FEISHU_APP_SECRET = EncryptedField(max_length=256, required=False, label='App Secret')
AUTH_FEISHU = serializers.BooleanField(default=False, label=_('Enable FeiShu Auth'))
FEISHU_VERSION = serializers.ChoiceField(
choices=VERSION_CHOICES, default='feishu', label=_('Version')
)

View File

@@ -105,9 +105,13 @@ class Session(OrgModelMixin):
def find_ok_relative_path_in_storage(self, storage):
session_paths = self.get_all_possible_relative_path()
for rel_path in session_paths:
if storage.exists(rel_path):
return rel_path
# storage 为多个外部存储时, 可能会因部分不可用,
# 抛出异常, 影响录像的获取
try:
if storage.exists(rel_path):
return rel_path
except:
pass
@property
def asset_obj(self):
return Asset.objects.get(id=self.asset_id)