mirror of https://github.com/jumpserver/jumpserver
commit
d672122c79
|
@ -123,6 +123,8 @@ class LoginACL(BaseACL):
|
||||||
'org_id': Organization.ROOT_ID,
|
'org_id': Organization.ROOT_ID,
|
||||||
}
|
}
|
||||||
ticket = Ticket.objects.create(**data)
|
ticket = Ticket.objects.create(**data)
|
||||||
ticket.create_process_map_and_node(self.reviewers.all())
|
applicant = self.user
|
||||||
ticket.open(self.user)
|
assignees = self.reviewers.all()
|
||||||
|
ticket.create_process_map_and_node(assignees, applicant)
|
||||||
|
ticket.open(applicant)
|
||||||
return ticket
|
return ticket
|
||||||
|
|
|
@ -97,7 +97,7 @@ class LoginAssetACL(BaseACL, OrgModelMixin):
|
||||||
'org_id': org_id,
|
'org_id': org_id,
|
||||||
}
|
}
|
||||||
ticket = Ticket.objects.create(**data)
|
ticket = Ticket.objects.create(**data)
|
||||||
ticket.create_process_map_and_node(assignees)
|
ticket.create_process_map_and_node(assignees, user)
|
||||||
ticket.open(applicant=user)
|
ticket.open(applicant=user)
|
||||||
return ticket
|
return ticket
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||||
from assets.serializers.base import AuthSerializerMixin
|
from assets.serializers.base import AuthSerializerMixin
|
||||||
from common.drf.serializers import MethodSerializer
|
from common.drf.serializers import MethodSerializer, SecretReadableMixin
|
||||||
from .attrs import (
|
from .attrs import (
|
||||||
category_serializer_classes_mapping,
|
category_serializer_classes_mapping,
|
||||||
type_serializer_classes_mapping,
|
type_serializer_classes_mapping,
|
||||||
|
@ -152,7 +152,7 @@ class AppAccountSerializer(AppSerializerMixin, AuthSerializerMixin, BulkOrgResou
|
||||||
return super().to_representation(instance)
|
return super().to_representation(instance)
|
||||||
|
|
||||||
|
|
||||||
class AppAccountSecretSerializer(AppAccountSerializer):
|
class AppAccountSecretSerializer(SecretReadableMixin, AppAccountSerializer):
|
||||||
class Meta(AppAccountSerializer.Meta):
|
class Meta(AppAccountSerializer.Meta):
|
||||||
fields_backup = [
|
fields_backup = [
|
||||||
'id', 'app_display', 'attrs', 'username', 'password', 'private_key',
|
'id', 'app_display', 'attrs', 'username', 'password', 'private_key',
|
||||||
|
|
|
@ -181,8 +181,10 @@ class CommandFilterRule(OrgModelMixin):
|
||||||
'org_id': org_id,
|
'org_id': org_id,
|
||||||
}
|
}
|
||||||
ticket = Ticket.objects.create(**data)
|
ticket = Ticket.objects.create(**data)
|
||||||
ticket.create_process_map_and_node(self.reviewers.all())
|
applicant = session.user_obj
|
||||||
ticket.open(applicant=session.user_obj)
|
assignees = self.reviewers.all()
|
||||||
|
ticket.create_process_map_and_node(assignees, applicant)
|
||||||
|
ticket.open(applicant)
|
||||||
return ticket
|
return ticket
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -7,6 +7,7 @@ from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||||
from .base import AuthSerializerMixin
|
from .base import AuthSerializerMixin
|
||||||
from .utils import validate_password_contains_left_double_curly_bracket
|
from .utils import validate_password_contains_left_double_curly_bracket
|
||||||
from common.utils.encode import ssh_pubkey_gen
|
from common.utils.encode import ssh_pubkey_gen
|
||||||
|
from common.drf.serializers import SecretReadableMixin
|
||||||
|
|
||||||
|
|
||||||
class AccountSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
class AccountSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||||
|
@ -70,7 +71,7 @@ class AccountSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||||
return super().to_representation(instance)
|
return super().to_representation(instance)
|
||||||
|
|
||||||
|
|
||||||
class AccountSecretSerializer(AccountSerializer):
|
class AccountSecretSerializer(SecretReadableMixin, AccountSerializer):
|
||||||
class Meta(AccountSerializer.Meta):
|
class Meta(AccountSerializer.Meta):
|
||||||
fields_backup = [
|
fields_backup = [
|
||||||
'hostname', 'ip', 'platform', 'protocols', 'username', 'password',
|
'hostname', 'ip', 'platform', 'protocols', 'username', 'password',
|
||||||
|
|
|
@ -4,6 +4,7 @@ from django.db.models import Count
|
||||||
|
|
||||||
from common.mixins.serializers import BulkSerializerMixin
|
from common.mixins.serializers import BulkSerializerMixin
|
||||||
from common.utils import ssh_pubkey_gen
|
from common.utils import ssh_pubkey_gen
|
||||||
|
from common.drf.fields import EncryptedField
|
||||||
from common.validators import alphanumeric_re, alphanumeric_cn_re, alphanumeric_win_re
|
from common.validators import alphanumeric_re, alphanumeric_cn_re, alphanumeric_win_re
|
||||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||||
from ..models import SystemUser, Asset
|
from ..models import SystemUser, Asset
|
||||||
|
@ -26,6 +27,9 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||||
auto_generate_key = serializers.BooleanField(initial=True, required=False, write_only=True)
|
auto_generate_key = serializers.BooleanField(initial=True, required=False, write_only=True)
|
||||||
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type display'))
|
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type display'))
|
||||||
ssh_key_fingerprint = serializers.ReadOnlyField(label=_('SSH key fingerprint'))
|
ssh_key_fingerprint = serializers.ReadOnlyField(label=_('SSH key fingerprint'))
|
||||||
|
token = EncryptedField(
|
||||||
|
label=_('Token'), required=False, write_only=True, style={'base_template': 'textarea.html'}
|
||||||
|
)
|
||||||
applications_amount = serializers.IntegerField(
|
applications_amount = serializers.IntegerField(
|
||||||
source='apps_amount', read_only=True, label=_('Apps amount')
|
source='apps_amount', read_only=True, label=_('Apps amount')
|
||||||
)
|
)
|
||||||
|
|
|
@ -205,12 +205,13 @@ class DingTalkQRLoginView(DingTalkQRMixin, METAMixin, View):
|
||||||
permission_classes = (AllowAny,)
|
permission_classes = (AllowAny,)
|
||||||
|
|
||||||
def get(self, request: HttpRequest):
|
def get(self, request: HttpRequest):
|
||||||
redirect_url = request.GET.get('redirect_url')
|
redirect_url = request.GET.get('redirect_url') or reverse('index')
|
||||||
|
next_url = self.get_next_url_from_meta() or reverse('index')
|
||||||
|
|
||||||
redirect_uri = reverse('authentication:dingtalk-qr-login-callback', external=True)
|
redirect_uri = reverse('authentication:dingtalk-qr-login-callback', external=True)
|
||||||
redirect_uri += '?' + urlencode({
|
redirect_uri += '?' + urlencode({
|
||||||
'redirect_url': redirect_url,
|
'redirect_url': redirect_url,
|
||||||
'next': self.get_next_url_from_meta()
|
'next': next_url,
|
||||||
})
|
})
|
||||||
|
|
||||||
url = self.get_qr_url(redirect_uri)
|
url = self.get_qr_url(redirect_uri)
|
||||||
|
|
|
@ -170,10 +170,11 @@ class FeiShuQRLoginView(FeiShuQRMixin, View):
|
||||||
permission_classes = (AllowAny,)
|
permission_classes = (AllowAny,)
|
||||||
|
|
||||||
def get(self, request: HttpRequest):
|
def get(self, request: HttpRequest):
|
||||||
redirect_url = request.GET.get('redirect_url')
|
redirect_url = request.GET.get('redirect_url') or reverse('index')
|
||||||
|
|
||||||
redirect_uri = reverse('authentication:feishu-qr-login-callback', external=True)
|
redirect_uri = reverse('authentication:feishu-qr-login-callback', external=True)
|
||||||
redirect_uri += '?' + urlencode({'redirect_url': redirect_url})
|
redirect_uri += '?' + urlencode({
|
||||||
|
'redirect_url': redirect_url,
|
||||||
|
})
|
||||||
|
|
||||||
url = self.get_qr_url(redirect_uri)
|
url = self.get_qr_url(redirect_uri)
|
||||||
return HttpResponseRedirect(url)
|
return HttpResponseRedirect(url)
|
||||||
|
|
|
@ -201,12 +201,12 @@ class WeComQRLoginView(WeComQRMixin, METAMixin, View):
|
||||||
permission_classes = (AllowAny,)
|
permission_classes = (AllowAny,)
|
||||||
|
|
||||||
def get(self, request: HttpRequest):
|
def get(self, request: HttpRequest):
|
||||||
redirect_url = request.GET.get('redirect_url')
|
redirect_url = request.GET.get('redirect_url') or reverse('index')
|
||||||
|
next_url = self.get_next_url_from_meta() or reverse('index')
|
||||||
redirect_uri = reverse('authentication:wecom-qr-login-callback', external=True)
|
redirect_uri = reverse('authentication:wecom-qr-login-callback', external=True)
|
||||||
redirect_uri += '?' + urlencode({
|
redirect_uri += '?' + urlencode({
|
||||||
'redirect_url': redirect_url,
|
'redirect_url': redirect_url,
|
||||||
'next': self.get_next_url_from_meta()
|
'next': next_url,
|
||||||
})
|
})
|
||||||
|
|
||||||
url = self.get_qr_url(redirect_uri)
|
url = self.get_qr_url(redirect_uri)
|
||||||
|
|
|
@ -27,8 +27,10 @@ class ReadableHiddenField(serializers.HiddenField):
|
||||||
|
|
||||||
|
|
||||||
class EncryptedField(serializers.CharField):
|
class EncryptedField(serializers.CharField):
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, write_only=None, **kwargs):
|
||||||
kwargs['write_only'] = True
|
if write_only is None:
|
||||||
|
write_only = True
|
||||||
|
kwargs['write_only'] = write_only
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
|
|
||||||
def to_internal_value(self, value):
|
def to_internal_value(self, value):
|
||||||
|
|
|
@ -8,10 +8,12 @@ from common.mixins import BulkListSerializerMixin
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from rest_framework.utils.serializer_helpers import BindingDict
|
from rest_framework.utils.serializer_helpers import BindingDict
|
||||||
from common.mixins.serializers import BulkSerializerMixin
|
from common.mixins.serializers import BulkSerializerMixin
|
||||||
|
from common.drf.fields import EncryptedField
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'MethodSerializer',
|
'MethodSerializer',
|
||||||
'EmptySerializer', 'BulkModelSerializer', 'AdaptedBulkListSerializer', 'CeleryTaskSerializer'
|
'EmptySerializer', 'BulkModelSerializer', 'AdaptedBulkListSerializer', 'CeleryTaskSerializer',
|
||||||
|
'SecretReadableMixin'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,3 +85,20 @@ class CeleryTaskSerializer(serializers.Serializer):
|
||||||
task = serializers.CharField(read_only=True)
|
task = serializers.CharField(read_only=True)
|
||||||
|
|
||||||
|
|
||||||
|
class SecretReadableMixin(serializers.Serializer):
|
||||||
|
""" 加密字段 (EncryptedField) 可读性 """
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(SecretReadableMixin, self).__init__(*args, **kwargs)
|
||||||
|
if not hasattr(self, 'Meta') or not hasattr(self.Meta, 'extra_kwargs'):
|
||||||
|
return
|
||||||
|
extra_kwargs = self.Meta.extra_kwargs
|
||||||
|
for field_name, serializer_field in self.fields.items():
|
||||||
|
if not isinstance(serializer_field, EncryptedField):
|
||||||
|
continue
|
||||||
|
if field_name not in extra_kwargs:
|
||||||
|
continue
|
||||||
|
field_extra_kwargs = extra_kwargs[field_name]
|
||||||
|
if 'write_only' not in field_extra_kwargs:
|
||||||
|
continue
|
||||||
|
serializer_field.write_only = field_extra_kwargs['write_only']
|
||||||
|
|
|
@ -389,6 +389,8 @@ class Config(dict):
|
||||||
'FTP_LOG_KEEP_DAYS': 200,
|
'FTP_LOG_KEEP_DAYS': 200,
|
||||||
'CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS': 30,
|
'CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS': 30,
|
||||||
|
|
||||||
|
'TICKETS_ENABLED': True,
|
||||||
|
|
||||||
# 废弃的
|
# 废弃的
|
||||||
'DEFAULT_ORG_SHOW_ALL_USERS': True,
|
'DEFAULT_ORG_SHOW_ALL_USERS': True,
|
||||||
'ORG_CHANGE_TO_URL': '',
|
'ORG_CHANGE_TO_URL': '',
|
||||||
|
|
|
@ -119,6 +119,7 @@ CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED = CONFIG.CHANGE_AUTH_PLAN_SECURE_MODE_ENABL
|
||||||
|
|
||||||
DATETIME_DISPLAY_FORMAT = '%Y-%m-%d %H:%M:%S'
|
DATETIME_DISPLAY_FORMAT = '%Y-%m-%d %H:%M:%S'
|
||||||
|
|
||||||
|
TICKETS_ENABLED = CONFIG.TICKETS_ENABLED
|
||||||
REFERER_CHECK_ENABLED = CONFIG.REFERER_CHECK_ENABLED
|
REFERER_CHECK_ENABLED = CONFIG.REFERER_CHECK_ENABLED
|
||||||
|
|
||||||
CONNECTION_TOKEN_ENABLED = CONFIG.CONNECTION_TOKEN_ENABLED
|
CONNECTION_TOKEN_ENABLED = CONFIG.CONNECTION_TOKEN_ENABLED
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:01a52223f421d736b00a600f623d28ac4a43e97a30f5e9cbebc3e6d18ed4527e
|
oid sha256:843b6dffe6af09073053e21f65be4c8264e6dee05509b375c8191dde8c9079b6
|
||||||
size 127324
|
size 127386
|
||||||
|
|
|
@ -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: 2022-05-16 17:43+0800\n"
|
"POT-Creation-Date: 2022-05-17 18:02+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"
|
||||||
|
@ -758,10 +758,12 @@ msgstr "接続性"
|
||||||
msgid "Date verified"
|
msgid "Date verified"
|
||||||
msgstr "確認済みの日付"
|
msgstr "確認済みの日付"
|
||||||
|
|
||||||
#: assets/models/base.py:177 audits/signal_handlers.py:48
|
#: assets/models/base.py:177 assets/serializers/base.py:14
|
||||||
|
#: assets/serializers/base.py:36 audits/signal_handlers.py:48
|
||||||
#: authentication/forms.py:32
|
#: authentication/forms.py:32
|
||||||
#: authentication/templates/authentication/login.html:182
|
#: authentication/templates/authentication/login.html:182
|
||||||
#: settings/serializers/auth/ldap.py:46 users/forms/profile.py:22
|
#: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:46
|
||||||
|
#: users/forms/profile.py:22 users/serializers/user.py:92
|
||||||
#: users/templates/users/_msg_user_created.html:13
|
#: users/templates/users/_msg_user_created.html:13
|
||||||
#: users/templates/users/user_password_verify.html:18
|
#: users/templates/users/user_password_verify.html:18
|
||||||
#: xpack/plugins/change_auth_plan/models/base.py:42
|
#: xpack/plugins/change_auth_plan/models/base.py:42
|
||||||
|
@ -771,7 +773,8 @@ msgstr "確認済みの日付"
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "パスワード"
|
msgstr "パスワード"
|
||||||
|
|
||||||
#: assets/models/base.py:178 xpack/plugins/change_auth_plan/models/asset.py:53
|
#: assets/models/base.py:178 assets/serializers/base.py:39
|
||||||
|
#: xpack/plugins/change_auth_plan/models/asset.py:53
|
||||||
#: xpack/plugins/change_auth_plan/models/asset.py:130
|
#: xpack/plugins/change_auth_plan/models/asset.py:130
|
||||||
#: xpack/plugins/change_auth_plan/models/asset.py:206
|
#: xpack/plugins/change_auth_plan/models/asset.py:206
|
||||||
msgid "SSH private key"
|
msgid "SSH private key"
|
||||||
|
@ -1120,11 +1123,15 @@ msgstr "定期的なパフォーマンス"
|
||||||
msgid "Currently only mail sending is supported"
|
msgid "Currently only mail sending is supported"
|
||||||
msgstr "現在、メール送信のみがサポートされています"
|
msgstr "現在、メール送信のみがサポートされています"
|
||||||
|
|
||||||
#: assets/serializers/base.py:39
|
#: assets/serializers/base.py:15 users/models/user.py:689
|
||||||
|
msgid "Private key"
|
||||||
|
msgstr "ssh秘密鍵"
|
||||||
|
|
||||||
|
#: assets/serializers/base.py:43
|
||||||
msgid "Key password"
|
msgid "Key password"
|
||||||
msgstr "キーパスワード"
|
msgstr "キーパスワード"
|
||||||
|
|
||||||
#: assets/serializers/base.py:52
|
#: assets/serializers/base.py:56
|
||||||
msgid "private key invalid or passphrase error"
|
msgid "private key invalid or passphrase error"
|
||||||
msgstr "秘密鍵が無効またはpassphraseエラー"
|
msgstr "秘密鍵が無効またはpassphraseエラー"
|
||||||
|
|
||||||
|
@ -2102,7 +2109,7 @@ msgstr "バインディングリマインダー"
|
||||||
#: perms/serializers/application/permission.py:20
|
#: perms/serializers/application/permission.py:20
|
||||||
#: perms/serializers/application/permission.py:41
|
#: perms/serializers/application/permission.py:41
|
||||||
#: perms/serializers/asset/permission.py:19
|
#: perms/serializers/asset/permission.py:19
|
||||||
#: perms/serializers/asset/permission.py:45 users/serializers/user.py:143
|
#: perms/serializers/asset/permission.py:45 users/serializers/user.py:145
|
||||||
msgid "Is valid"
|
msgid "Is valid"
|
||||||
msgstr "有効です"
|
msgstr "有効です"
|
||||||
|
|
||||||
|
@ -3063,7 +3070,7 @@ msgstr "Organization {} のアプリケーション権限"
|
||||||
#: perms/serializers/application/permission.py:40
|
#: perms/serializers/application/permission.py:40
|
||||||
#: perms/serializers/asset/permission.py:20
|
#: perms/serializers/asset/permission.py:20
|
||||||
#: perms/serializers/asset/permission.py:44 users/serializers/user.py:87
|
#: perms/serializers/asset/permission.py:44 users/serializers/user.py:87
|
||||||
#: users/serializers/user.py:145
|
#: users/serializers/user.py:147
|
||||||
msgid "Is expired"
|
msgid "Is expired"
|
||||||
msgstr "期限切れです"
|
msgstr "期限切れです"
|
||||||
|
|
||||||
|
@ -3773,6 +3780,10 @@ msgstr "アナウンスの有効化"
|
||||||
msgid "Announcement"
|
msgid "Announcement"
|
||||||
msgstr "発表"
|
msgstr "発表"
|
||||||
|
|
||||||
|
#: settings/serializers/basic.py:46
|
||||||
|
msgid "Enable tickets"
|
||||||
|
msgstr "チケットを有効にする"
|
||||||
|
|
||||||
#: settings/serializers/cleaning.py:10
|
#: settings/serializers/cleaning.py:10
|
||||||
msgid "Login log keep days"
|
msgid "Login log keep days"
|
||||||
msgstr "ログインログは日数を保持します"
|
msgstr "ログインログは日数を保持します"
|
||||||
|
@ -5640,7 +5651,7 @@ msgstr "強制有効"
|
||||||
msgid "Local"
|
msgid "Local"
|
||||||
msgstr "ローカル"
|
msgstr "ローカル"
|
||||||
|
|
||||||
#: users/models/user.py:673 users/serializers/user.py:144
|
#: users/models/user.py:673 users/serializers/user.py:146
|
||||||
msgid "Is service account"
|
msgid "Is service account"
|
||||||
msgstr "サービスアカウントです"
|
msgstr "サービスアカウントです"
|
||||||
|
|
||||||
|
@ -5652,10 +5663,6 @@ msgstr "アバター"
|
||||||
msgid "Wechat"
|
msgid "Wechat"
|
||||||
msgstr "微信"
|
msgstr "微信"
|
||||||
|
|
||||||
#: users/models/user.py:689
|
|
||||||
msgid "Private key"
|
|
||||||
msgstr "ssh秘密鍵"
|
|
||||||
|
|
||||||
#: users/models/user.py:711
|
#: users/models/user.py:711
|
||||||
msgid "Source"
|
msgid "Source"
|
||||||
msgstr "ソース"
|
msgstr "ソース"
|
||||||
|
@ -5739,7 +5746,7 @@ msgstr "新しいパスワードを最後の {} 個のパスワードにする
|
||||||
msgid "The newly set password is inconsistent"
|
msgid "The newly set password is inconsistent"
|
||||||
msgstr "新しく設定されたパスワードが一致しない"
|
msgstr "新しく設定されたパスワードが一致しない"
|
||||||
|
|
||||||
#: users/serializers/profile.py:147 users/serializers/user.py:142
|
#: users/serializers/profile.py:147 users/serializers/user.py:144
|
||||||
msgid "Is first login"
|
msgid "Is first login"
|
||||||
msgstr "最初のログインです"
|
msgstr "最初のログインです"
|
||||||
|
|
||||||
|
@ -5777,63 +5784,63 @@ msgstr "ログインブロック"
|
||||||
msgid "Can public key authentication"
|
msgid "Can public key authentication"
|
||||||
msgstr "公開鍵認証が可能"
|
msgstr "公開鍵認証が可能"
|
||||||
|
|
||||||
#: users/serializers/user.py:146
|
#: users/serializers/user.py:148
|
||||||
msgid "Avatar url"
|
msgid "Avatar url"
|
||||||
msgstr "アバターURL"
|
msgstr "アバターURL"
|
||||||
|
|
||||||
#: users/serializers/user.py:148
|
#: users/serializers/user.py:150
|
||||||
msgid "Groups name"
|
msgid "Groups name"
|
||||||
msgstr "グループ名"
|
msgstr "グループ名"
|
||||||
|
|
||||||
#: users/serializers/user.py:149
|
#: users/serializers/user.py:151
|
||||||
msgid "Source name"
|
msgid "Source name"
|
||||||
msgstr "ソース名"
|
msgstr "ソース名"
|
||||||
|
|
||||||
#: users/serializers/user.py:150
|
#: users/serializers/user.py:152
|
||||||
msgid "Organization role name"
|
msgid "Organization role name"
|
||||||
msgstr "組織の役割名"
|
msgstr "組織の役割名"
|
||||||
|
|
||||||
#: users/serializers/user.py:151
|
#: users/serializers/user.py:153
|
||||||
msgid "Super role name"
|
msgid "Super role name"
|
||||||
msgstr "スーパーロール名"
|
msgstr "スーパーロール名"
|
||||||
|
|
||||||
#: users/serializers/user.py:152
|
#: users/serializers/user.py:154
|
||||||
msgid "Total role name"
|
msgid "Total role name"
|
||||||
msgstr "合計ロール名"
|
msgstr "合計ロール名"
|
||||||
|
|
||||||
#: users/serializers/user.py:154
|
#: users/serializers/user.py:156
|
||||||
msgid "Is wecom bound"
|
msgid "Is wecom bound"
|
||||||
msgstr "企業の微信をバインドしているかどうか"
|
msgstr "企業の微信をバインドしているかどうか"
|
||||||
|
|
||||||
#: users/serializers/user.py:155
|
#: users/serializers/user.py:157
|
||||||
msgid "Is dingtalk bound"
|
msgid "Is dingtalk bound"
|
||||||
msgstr "ピンをバインドしているかどうか"
|
msgstr "ピンをバインドしているかどうか"
|
||||||
|
|
||||||
#: users/serializers/user.py:156
|
#: users/serializers/user.py:158
|
||||||
msgid "Is feishu bound"
|
msgid "Is feishu bound"
|
||||||
msgstr "飛本を縛ったかどうか"
|
msgstr "飛本を縛ったかどうか"
|
||||||
|
|
||||||
#: users/serializers/user.py:157
|
#: users/serializers/user.py:159
|
||||||
msgid "Is OTP bound"
|
msgid "Is OTP bound"
|
||||||
msgstr "仮想MFAがバインドされているか"
|
msgstr "仮想MFAがバインドされているか"
|
||||||
|
|
||||||
#: users/serializers/user.py:159
|
#: users/serializers/user.py:161
|
||||||
msgid "System role name"
|
msgid "System role name"
|
||||||
msgstr "システムロール名"
|
msgstr "システムロール名"
|
||||||
|
|
||||||
#: users/serializers/user.py:199
|
#: users/serializers/user.py:201
|
||||||
msgid "User cannot self-update fields: {}"
|
msgid "User cannot self-update fields: {}"
|
||||||
msgstr "ユーザーは自分のフィールドを更新できません: {}"
|
msgstr "ユーザーは自分のフィールドを更新できません: {}"
|
||||||
|
|
||||||
#: users/serializers/user.py:256
|
#: users/serializers/user.py:258
|
||||||
msgid "Select users"
|
msgid "Select users"
|
||||||
msgstr "ユーザーの選択"
|
msgstr "ユーザーの選択"
|
||||||
|
|
||||||
#: users/serializers/user.py:257
|
#: users/serializers/user.py:259
|
||||||
msgid "For security, only list several users"
|
msgid "For security, only list several users"
|
||||||
msgstr "セキュリティのために、複数のユーザーのみをリストします"
|
msgstr "セキュリティのために、複数のユーザーのみをリストします"
|
||||||
|
|
||||||
#: users/serializers/user.py:292
|
#: users/serializers/user.py:294
|
||||||
msgid "name not unique"
|
msgid "name not unique"
|
||||||
msgstr "名前が一意ではない"
|
msgstr "名前が一意ではない"
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:e4a00b4e1a3bc944c968987fd3c65798fb39fa552e91457693ec8fcb597820f0
|
oid sha256:a78975a5a6669bfcc0f99bc4d47811be82a0620e873e51e4a17d06548e3b1e7f
|
||||||
size 105225
|
size 105269
|
||||||
|
|
|
@ -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: 2022-05-16 17:43+0800\n"
|
"POT-Creation-Date: 2022-05-17 18:02+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"
|
||||||
|
@ -753,10 +753,12 @@ msgstr "可连接性"
|
||||||
msgid "Date verified"
|
msgid "Date verified"
|
||||||
msgstr "校验日期"
|
msgstr "校验日期"
|
||||||
|
|
||||||
#: assets/models/base.py:177 audits/signal_handlers.py:48
|
#: assets/models/base.py:177 assets/serializers/base.py:14
|
||||||
|
#: assets/serializers/base.py:36 audits/signal_handlers.py:48
|
||||||
#: authentication/forms.py:32
|
#: authentication/forms.py:32
|
||||||
#: authentication/templates/authentication/login.html:182
|
#: authentication/templates/authentication/login.html:182
|
||||||
#: settings/serializers/auth/ldap.py:46 users/forms/profile.py:22
|
#: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:46
|
||||||
|
#: users/forms/profile.py:22 users/serializers/user.py:92
|
||||||
#: users/templates/users/_msg_user_created.html:13
|
#: users/templates/users/_msg_user_created.html:13
|
||||||
#: users/templates/users/user_password_verify.html:18
|
#: users/templates/users/user_password_verify.html:18
|
||||||
#: xpack/plugins/change_auth_plan/models/base.py:42
|
#: xpack/plugins/change_auth_plan/models/base.py:42
|
||||||
|
@ -766,7 +768,8 @@ msgstr "校验日期"
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "密码"
|
msgstr "密码"
|
||||||
|
|
||||||
#: assets/models/base.py:178 xpack/plugins/change_auth_plan/models/asset.py:53
|
#: assets/models/base.py:178 assets/serializers/base.py:39
|
||||||
|
#: xpack/plugins/change_auth_plan/models/asset.py:53
|
||||||
#: xpack/plugins/change_auth_plan/models/asset.py:130
|
#: xpack/plugins/change_auth_plan/models/asset.py:130
|
||||||
#: xpack/plugins/change_auth_plan/models/asset.py:206
|
#: xpack/plugins/change_auth_plan/models/asset.py:206
|
||||||
msgid "SSH private key"
|
msgid "SSH private key"
|
||||||
|
@ -1112,11 +1115,15 @@ msgstr "定时执行"
|
||||||
msgid "Currently only mail sending is supported"
|
msgid "Currently only mail sending is supported"
|
||||||
msgstr "当前只支持邮件发送"
|
msgstr "当前只支持邮件发送"
|
||||||
|
|
||||||
#: assets/serializers/base.py:39
|
#: assets/serializers/base.py:15 users/models/user.py:689
|
||||||
|
msgid "Private key"
|
||||||
|
msgstr "ssh私钥"
|
||||||
|
|
||||||
|
#: assets/serializers/base.py:43
|
||||||
msgid "Key password"
|
msgid "Key password"
|
||||||
msgstr "密钥密码"
|
msgstr "密钥密码"
|
||||||
|
|
||||||
#: assets/serializers/base.py:52
|
#: assets/serializers/base.py:56
|
||||||
msgid "private key invalid or passphrase error"
|
msgid "private key invalid or passphrase error"
|
||||||
msgstr "密钥不合法或密钥密码错误"
|
msgstr "密钥不合法或密钥密码错误"
|
||||||
|
|
||||||
|
@ -2081,7 +2088,7 @@ msgstr "绑定提醒"
|
||||||
#: perms/serializers/application/permission.py:20
|
#: perms/serializers/application/permission.py:20
|
||||||
#: perms/serializers/application/permission.py:41
|
#: perms/serializers/application/permission.py:41
|
||||||
#: perms/serializers/asset/permission.py:19
|
#: perms/serializers/asset/permission.py:19
|
||||||
#: perms/serializers/asset/permission.py:45 users/serializers/user.py:143
|
#: perms/serializers/asset/permission.py:45 users/serializers/user.py:145
|
||||||
msgid "Is valid"
|
msgid "Is valid"
|
||||||
msgstr "账号是否有效"
|
msgstr "账号是否有效"
|
||||||
|
|
||||||
|
@ -3027,7 +3034,7 @@ msgstr "组织 ({}) 的应用授权"
|
||||||
#: perms/serializers/application/permission.py:40
|
#: perms/serializers/application/permission.py:40
|
||||||
#: perms/serializers/asset/permission.py:20
|
#: perms/serializers/asset/permission.py:20
|
||||||
#: perms/serializers/asset/permission.py:44 users/serializers/user.py:87
|
#: perms/serializers/asset/permission.py:44 users/serializers/user.py:87
|
||||||
#: users/serializers/user.py:145
|
#: users/serializers/user.py:147
|
||||||
msgid "Is expired"
|
msgid "Is expired"
|
||||||
msgstr "已过期"
|
msgstr "已过期"
|
||||||
|
|
||||||
|
@ -3733,6 +3740,10 @@ msgstr "启用公告"
|
||||||
msgid "Announcement"
|
msgid "Announcement"
|
||||||
msgstr "公告"
|
msgstr "公告"
|
||||||
|
|
||||||
|
#: settings/serializers/basic.py:46
|
||||||
|
msgid "Enable tickets"
|
||||||
|
msgstr "启用工单"
|
||||||
|
|
||||||
#: settings/serializers/cleaning.py:10
|
#: settings/serializers/cleaning.py:10
|
||||||
msgid "Login log keep days"
|
msgid "Login log keep days"
|
||||||
msgstr "登录日志"
|
msgstr "登录日志"
|
||||||
|
@ -5562,7 +5573,7 @@ msgstr "强制启用"
|
||||||
msgid "Local"
|
msgid "Local"
|
||||||
msgstr "数据库"
|
msgstr "数据库"
|
||||||
|
|
||||||
#: users/models/user.py:673 users/serializers/user.py:144
|
#: users/models/user.py:673 users/serializers/user.py:146
|
||||||
msgid "Is service account"
|
msgid "Is service account"
|
||||||
msgstr "服务账号"
|
msgstr "服务账号"
|
||||||
|
|
||||||
|
@ -5574,10 +5585,6 @@ msgstr "头像"
|
||||||
msgid "Wechat"
|
msgid "Wechat"
|
||||||
msgstr "微信"
|
msgstr "微信"
|
||||||
|
|
||||||
#: users/models/user.py:689
|
|
||||||
msgid "Private key"
|
|
||||||
msgstr "ssh私钥"
|
|
||||||
|
|
||||||
#: users/models/user.py:711
|
#: users/models/user.py:711
|
||||||
msgid "Source"
|
msgid "Source"
|
||||||
msgstr "来源"
|
msgstr "来源"
|
||||||
|
@ -5661,7 +5668,7 @@ msgstr "新密码不能是最近 {} 次的密码"
|
||||||
msgid "The newly set password is inconsistent"
|
msgid "The newly set password is inconsistent"
|
||||||
msgstr "两次密码不一致"
|
msgstr "两次密码不一致"
|
||||||
|
|
||||||
#: users/serializers/profile.py:147 users/serializers/user.py:142
|
#: users/serializers/profile.py:147 users/serializers/user.py:144
|
||||||
msgid "Is first login"
|
msgid "Is first login"
|
||||||
msgstr "首次登录"
|
msgstr "首次登录"
|
||||||
|
|
||||||
|
@ -5699,63 +5706,63 @@ msgstr "登录被阻塞"
|
||||||
msgid "Can public key authentication"
|
msgid "Can public key authentication"
|
||||||
msgstr "能否公钥认证"
|
msgstr "能否公钥认证"
|
||||||
|
|
||||||
#: users/serializers/user.py:146
|
#: users/serializers/user.py:148
|
||||||
msgid "Avatar url"
|
msgid "Avatar url"
|
||||||
msgstr "头像路径"
|
msgstr "头像路径"
|
||||||
|
|
||||||
#: users/serializers/user.py:148
|
#: users/serializers/user.py:150
|
||||||
msgid "Groups name"
|
msgid "Groups name"
|
||||||
msgstr "用户组名"
|
msgstr "用户组名"
|
||||||
|
|
||||||
#: users/serializers/user.py:149
|
#: users/serializers/user.py:151
|
||||||
msgid "Source name"
|
msgid "Source name"
|
||||||
msgstr "用户来源名"
|
msgstr "用户来源名"
|
||||||
|
|
||||||
#: users/serializers/user.py:150
|
#: users/serializers/user.py:152
|
||||||
msgid "Organization role name"
|
msgid "Organization role name"
|
||||||
msgstr "组织角色名称"
|
msgstr "组织角色名称"
|
||||||
|
|
||||||
#: users/serializers/user.py:151
|
#: users/serializers/user.py:153
|
||||||
msgid "Super role name"
|
msgid "Super role name"
|
||||||
msgstr "超级角色名称"
|
msgstr "超级角色名称"
|
||||||
|
|
||||||
#: users/serializers/user.py:152
|
#: users/serializers/user.py:154
|
||||||
msgid "Total role name"
|
msgid "Total role name"
|
||||||
msgstr "汇总角色名称"
|
msgstr "汇总角色名称"
|
||||||
|
|
||||||
#: users/serializers/user.py:154
|
#: users/serializers/user.py:156
|
||||||
msgid "Is wecom bound"
|
msgid "Is wecom bound"
|
||||||
msgstr "是否绑定了企业微信"
|
msgstr "是否绑定了企业微信"
|
||||||
|
|
||||||
#: users/serializers/user.py:155
|
#: users/serializers/user.py:157
|
||||||
msgid "Is dingtalk bound"
|
msgid "Is dingtalk bound"
|
||||||
msgstr "是否绑定了钉钉"
|
msgstr "是否绑定了钉钉"
|
||||||
|
|
||||||
#: users/serializers/user.py:156
|
#: users/serializers/user.py:158
|
||||||
msgid "Is feishu bound"
|
msgid "Is feishu bound"
|
||||||
msgstr "是否绑定了飞书"
|
msgstr "是否绑定了飞书"
|
||||||
|
|
||||||
#: users/serializers/user.py:157
|
#: users/serializers/user.py:159
|
||||||
msgid "Is OTP bound"
|
msgid "Is OTP bound"
|
||||||
msgstr "是否绑定了虚拟 MFA"
|
msgstr "是否绑定了虚拟 MFA"
|
||||||
|
|
||||||
#: users/serializers/user.py:159
|
#: users/serializers/user.py:161
|
||||||
msgid "System role name"
|
msgid "System role name"
|
||||||
msgstr "系统角色名称"
|
msgstr "系统角色名称"
|
||||||
|
|
||||||
#: users/serializers/user.py:199
|
#: users/serializers/user.py:201
|
||||||
msgid "User cannot self-update fields: {}"
|
msgid "User cannot self-update fields: {}"
|
||||||
msgstr "用户不能更新自己的字段: {}"
|
msgstr "用户不能更新自己的字段: {}"
|
||||||
|
|
||||||
#: users/serializers/user.py:256
|
#: users/serializers/user.py:258
|
||||||
msgid "Select users"
|
msgid "Select users"
|
||||||
msgstr "选择用户"
|
msgstr "选择用户"
|
||||||
|
|
||||||
#: users/serializers/user.py:257
|
#: users/serializers/user.py:259
|
||||||
msgid "For security, only list several users"
|
msgid "For security, only list several users"
|
||||||
msgstr "为了安全,仅列出几个用户"
|
msgstr "为了安全,仅列出几个用户"
|
||||||
|
|
||||||
#: users/serializers/user.py:292
|
#: users/serializers/user.py:294
|
||||||
msgid "name not unique"
|
msgid "name not unique"
|
||||||
msgstr "名称重复"
|
msgstr "名称重复"
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ class BasicSettingSerializer(serializers.Serializer):
|
||||||
)
|
)
|
||||||
ANNOUNCEMENT_ENABLED = serializers.BooleanField(label=_('Enable announcement'), default=True)
|
ANNOUNCEMENT_ENABLED = serializers.BooleanField(label=_('Enable announcement'), default=True)
|
||||||
ANNOUNCEMENT = AnnouncementSerializer(label=_("Announcement"))
|
ANNOUNCEMENT = AnnouncementSerializer(label=_("Announcement"))
|
||||||
|
TICKETS_ENABLED = serializers.BooleanField(required=False, default=True, label=_("Enable tickets"))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def validate_SITE_URL(s):
|
def validate_SITE_URL(s):
|
||||||
|
|
|
@ -40,4 +40,6 @@ class PrivateSettingSerializer(PublicSettingSerializer):
|
||||||
TERMINAL_KOKO_SSH_ENABLED = serializers.BooleanField()
|
TERMINAL_KOKO_SSH_ENABLED = serializers.BooleanField()
|
||||||
|
|
||||||
ANNOUNCEMENT_ENABLED = serializers.BooleanField()
|
ANNOUNCEMENT_ENABLED = serializers.BooleanField()
|
||||||
ANNOUNCEMENT = serializers.DictField()
|
ANNOUNCEMENT = serializers.CharField()
|
||||||
|
|
||||||
|
TICKETS_ENABLED = serializers.BooleanField()
|
||||||
|
|
|
@ -53,9 +53,10 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet):
|
||||||
|
|
||||||
def perform_create(self, serializer):
|
def perform_create(self, serializer):
|
||||||
instance = serializer.save()
|
instance = serializer.save()
|
||||||
instance.create_related_node()
|
applicant = self.request.user
|
||||||
instance.process_map = instance.create_process_map()
|
instance.create_related_node(applicant)
|
||||||
instance.open(applicant=self.request.user)
|
instance.process_map = instance.create_process_map(applicant)
|
||||||
|
instance.open(applicant)
|
||||||
|
|
||||||
@action(detail=False, methods=[POST], permission_classes=[RBACPermission, ])
|
@action(detail=False, methods=[POST], permission_classes=[RBACPermission, ])
|
||||||
def open(self, request, *args, **kwargs):
|
def open(self, request, *args, **kwargs):
|
||||||
|
|
|
@ -188,22 +188,30 @@ class Ticket(CommonModelMixin, StatusMixin, OrgModelMixin):
|
||||||
.exclude(state=ProcessStatus.notified).first()
|
.exclude(state=ProcessStatus.notified).first()
|
||||||
return processor.assignee if processor else None
|
return processor.assignee if processor else None
|
||||||
|
|
||||||
def create_related_node(self):
|
def ignore_applicant(self, assignees, applicant=None):
|
||||||
|
applicant = applicant if applicant else self.applicant
|
||||||
|
if len(assignees) != 1:
|
||||||
|
assignees = set(assignees) - {applicant, }
|
||||||
|
return list(assignees)
|
||||||
|
|
||||||
|
def create_related_node(self, applicant=None):
|
||||||
org_id = self.flow.org_id
|
org_id = self.flow.org_id
|
||||||
approval_rule = self.get_current_ticket_flow_approve()
|
approval_rule = self.get_current_ticket_flow_approve()
|
||||||
ticket_step = TicketStep.objects.create(ticket=self, level=self.approval_step)
|
ticket_step = TicketStep.objects.create(ticket=self, level=self.approval_step)
|
||||||
ticket_assignees = []
|
ticket_assignees = []
|
||||||
assignees = approval_rule.get_assignees(org_id=org_id)
|
assignees = approval_rule.get_assignees(org_id=org_id)
|
||||||
|
assignees = self.ignore_applicant(assignees, applicant)
|
||||||
for assignee in assignees:
|
for assignee in assignees:
|
||||||
ticket_assignees.append(TicketAssignee(step=ticket_step, assignee=assignee))
|
ticket_assignees.append(TicketAssignee(step=ticket_step, assignee=assignee))
|
||||||
TicketAssignee.objects.bulk_create(ticket_assignees)
|
TicketAssignee.objects.bulk_create(ticket_assignees)
|
||||||
|
|
||||||
def create_process_map(self):
|
def create_process_map(self, applicant=None):
|
||||||
org_id = self.flow.org_id
|
org_id = self.flow.org_id
|
||||||
approval_rules = self.flow.rules.order_by('level')
|
approval_rules = self.flow.rules.order_by('level')
|
||||||
nodes = list()
|
nodes = list()
|
||||||
for node in approval_rules:
|
for node in approval_rules:
|
||||||
assignees = node.get_assignees(org_id=org_id)
|
assignees = node.get_assignees(org_id=org_id)
|
||||||
|
assignees = self.ignore_applicant(assignees, applicant)
|
||||||
assignee_ids = [assignee.id for assignee in assignees]
|
assignee_ids = [assignee.id for assignee in assignees]
|
||||||
assignees_display = [str(assignee) for assignee in assignees]
|
assignees_display = [str(assignee) for assignee in assignees]
|
||||||
nodes.append(
|
nodes.append(
|
||||||
|
@ -217,7 +225,8 @@ class Ticket(CommonModelMixin, StatusMixin, OrgModelMixin):
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
# TODO 兼容不存在流的工单
|
# TODO 兼容不存在流的工单
|
||||||
def create_process_map_and_node(self, assignees):
|
def create_process_map_and_node(self, assignees, applicant):
|
||||||
|
assignees = self.ignore_applicant(assignees, applicant)
|
||||||
self.process_map = [{
|
self.process_map = [{
|
||||||
'approval_level': 1,
|
'approval_level': 1,
|
||||||
'state': 'notified',
|
'state': 'notified',
|
||||||
|
|
|
@ -46,11 +46,13 @@ def get_user_or_pre_auth_user(request):
|
||||||
|
|
||||||
|
|
||||||
def redirect_user_first_login_or_index(request, redirect_field_name):
|
def redirect_user_first_login_or_index(request, redirect_field_name):
|
||||||
url_in_post = request.POST.get(redirect_field_name)
|
url = request.POST.get(redirect_field_name)
|
||||||
if url_in_post:
|
if not url:
|
||||||
return url_in_post
|
url = request.GET.get(redirect_field_name)
|
||||||
url_in_get = request.GET.get(redirect_field_name, reverse('index'))
|
# 防止 next 地址为 None
|
||||||
return url_in_get
|
if not url or url.lower() in ['none']:
|
||||||
|
url = reverse('index')
|
||||||
|
return url
|
||||||
|
|
||||||
|
|
||||||
def generate_otp_uri(username, otp_secret_key=None, issuer="JumpServer"):
|
def generate_otp_uri(username, otp_secret_key=None, issuer="JumpServer"):
|
||||||
|
|
Loading…
Reference in New Issue