perf: 登录资产的 ACL 支持 ip 控制 (#10581)

Co-authored-by: ibuler <ibuler@qq.com>
pull/10583/head^2
fit2bot 2023-05-29 19:45:55 +08:00 committed by GitHub
parent fd7e821f11
commit e61227d694
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 235 additions and 129 deletions

View File

@ -1,6 +1,6 @@
# Generated by Django 3.2.17 on 2023-04-25 09:04 # Generated by Django 3.2.17 on 2023-04-25 09:04
from django.db import migrations from django.db import migrations, models
import common.db.fields import common.db.fields
@ -14,7 +14,7 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='commandfilteracl', model_name='commandfilteracl',
name='new_accounts', name='new_accounts',
field=common.db.fields.JSONManyToManyField(default=dict, to='assets.Account', verbose_name='Accounts'), field=models.JSONField(default=list, verbose_name='Accounts'),
), ),
migrations.AddField( migrations.AddField(
model_name='commandfilteracl', model_name='commandfilteracl',
@ -29,7 +29,7 @@ class Migration(migrations.Migration):
migrations.AddField( migrations.AddField(
model_name='loginassetacl', model_name='loginassetacl',
name='new_accounts', name='new_accounts',
field=common.db.fields.JSONManyToManyField(default=dict, to='assets.Account', verbose_name='Accounts'), field=models.JSONField(default=list, verbose_name='Accounts')
), ),
migrations.AddField( migrations.AddField(
model_name='loginassetacl', model_name='loginassetacl',

View File

@ -0,0 +1,18 @@
# Generated by Django 3.2.17 on 2023-05-26 09:00
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('acls', '0013_auto_20230426_1759'),
]
operations = [
migrations.AddField(
model_name='loginassetacl',
name='rules',
field=models.JSONField(default=dict, verbose_name='Rule'),
),
]

View File

@ -4,6 +4,8 @@ from django.utils.translation import gettext_lazy as _
from common.db.fields import JSONManyToManyField from common.db.fields import JSONManyToManyField
from common.db.models import JMSBaseModel from common.db.models import JMSBaseModel
from common.utils import contains_ip
from common.utils.time_period import contains_time_period
from orgs.mixins.models import OrgModelMixin from orgs.mixins.models import OrgModelMixin
__all__ = [ __all__ = [
@ -52,11 +54,35 @@ class BaseACL(JMSBaseModel):
def is_action(self, action): def is_action(self, action):
return self.action == action return self.action == action
@classmethod
def get_user_acls(cls, user):
return cls.objects.none()
@classmethod
def get_match_rule_acls(cls, user, ip, acl_qs=None):
if acl_qs is None:
acl_qs = cls.get_user_acls(user)
if not acl_qs:
return
for acl in acl_qs:
if acl.is_action(ActionChoices.review) and not acl.reviewers.exists():
continue
ip_group = acl.rules.get('ip_group')
time_periods = acl.rules.get('time_period')
is_contain_ip = contains_ip(ip, ip_group) if ip_group else True
is_contain_time_period = contains_time_period(time_periods) if time_periods else True
if is_contain_ip and is_contain_time_period:
# 满足条件,则返回
return acl
return None
class UserAssetAccountBaseACL(BaseACL, OrgModelMixin): class UserAssetAccountBaseACL(BaseACL, OrgModelMixin):
users = JSONManyToManyField('users.User', default=dict, verbose_name=_('Users')) users = JSONManyToManyField('users.User', default=dict, verbose_name=_('Users'))
assets = JSONManyToManyField('assets.Asset', default=dict, verbose_name=_('Assets')) assets = JSONManyToManyField('assets.Asset', default=dict, verbose_name=_('Assets'))
accounts = models.JSONField(default=list, verbose_name=_("Account")) accounts = models.JSONField(default=list, verbose_name=_("Accounts"))
class Meta(BaseACL.Meta): class Meta(BaseACL.Meta):
unique_together = ('name', 'org_id') unique_together = ('name', 'org_id')
@ -85,4 +111,4 @@ class UserAssetAccountBaseACL(BaseACL, OrgModelMixin):
kwargs['org_id'] = org_id kwargs['org_id'] = org_id
if kwargs: if kwargs:
queryset = queryset.filter(**kwargs) queryset = queryset.filter(**kwargs)
return queryset.distinct() return queryset.valid().distinct().order_by('priority', 'date_created')

View File

@ -2,15 +2,14 @@ from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.utils import get_request_ip, get_ip_city from common.utils import get_request_ip, get_ip_city
from common.utils.ip import contains_ip
from common.utils.time_period import contains_time_period
from common.utils.timezone import local_now_display from common.utils.timezone import local_now_display
from .base import BaseACL from .base import BaseACL
class LoginACL(BaseACL): class LoginACL(BaseACL):
user = models.ForeignKey( user = models.ForeignKey(
'users.User', on_delete=models.CASCADE, related_name='login_acls', verbose_name=_('User') 'users.User', on_delete=models.CASCADE,
related_name='login_acls', verbose_name=_('User')
) )
# 规则, ip_group, time_period # 规则, ip_group, time_period
rules = models.JSONField(default=dict, verbose_name=_('Rule')) rules = models.JSONField(default=dict, verbose_name=_('Rule'))
@ -29,23 +28,9 @@ class LoginACL(BaseACL):
def filter_acl(cls, user): def filter_acl(cls, user):
return user.login_acls.all().valid().distinct() return user.login_acls.all().valid().distinct()
@staticmethod @classmethod
def match(user, ip): def get_user_acls(cls, user):
acl_qs = LoginACL.filter_acl(user) return cls.filter_acl(user)
if not acl_qs:
return
for acl in acl_qs:
if acl.is_action(LoginACL.ActionChoices.review) and \
not acl.reviewers.exists():
continue
ip_group = acl.rules.get('ip_group')
time_periods = acl.rules.get('time_period')
is_contain_ip = contains_ip(ip, ip_group)
is_contain_time_period = contains_time_period(time_periods)
if is_contain_ip and is_contain_time_period:
# 满足条件,则返回
return acl
def create_confirm_ticket(self, request): def create_confirm_ticket(self, request):
from tickets import const from tickets import const

View File

@ -1,9 +1,13 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from .base import UserAssetAccountBaseACL from .base import UserAssetAccountBaseACL
class LoginAssetACL(UserAssetAccountBaseACL): class LoginAssetACL(UserAssetAccountBaseACL):
# 规则, ip_group, time_period
rules = models.JSONField(default=dict, verbose_name=_('Rule'))
class Meta(UserAssetAccountBaseACL.Meta): class Meta(UserAssetAccountBaseACL.Meta):
verbose_name = _('Login asset acl') verbose_name = _('Login asset acl')
abstract = False abstract = False

View File

@ -1,11 +1,20 @@
from orgs.mixins.serializers import BulkOrgResourceModelSerializer from django.utils.translation import gettext_lazy as _
from common.serializers import MethodSerializer
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from .base import BaseUserAssetAccountACLSerializerMixin as BaseSerializer from .base import BaseUserAssetAccountACLSerializerMixin as BaseSerializer
from .rules import RuleSerializer
from ..models import LoginAssetACL from ..models import LoginAssetACL
__all__ = ["LoginAssetACLSerializer"] __all__ = ["LoginAssetACLSerializer"]
class LoginAssetACLSerializer(BaseSerializer, BulkOrgResourceModelSerializer): class LoginAssetACLSerializer(BaseSerializer, BulkOrgResourceModelSerializer):
rules = MethodSerializer(label=_('Rule'))
class Meta(BaseSerializer.Meta): class Meta(BaseSerializer.Meta):
model = LoginAssetACL model = LoginAssetACL
fields = BaseSerializer.Meta.fields + ['rules']
def get_rules_serializer(self):
return RuleSerializer()

View File

@ -7,6 +7,6 @@ type:
- windows - windows
i18n: i18n:
Gather facts windows: Gather facts windows:
zh: 从 Windows 获取信息 zh: 从 Windows 获取硬件信息
en: Gather facts windows en: Gather facts windows
ja: Windowsから事実を取得する ja: Windowsから事実を取得する

View File

@ -1,12 +1,12 @@
# Generated by Django 2.1.7 on 2019-02-28 09:15 # Generated by Django 2.1.7 on 2019-02-28 09:15
from django.db import migrations, models, connection
import django.utils.timezone
import uuid import uuid
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('audits', '0004_operatelog_passwordchangelog_userloginlog'), ('audits', '0004_operatelog_passwordchangelog_userloginlog'),
('users', '0019_auto_20190304_1459'), ('users', '0019_auto_20190304_1459'),
@ -22,7 +22,7 @@ class Migration(migrations.Migration):
('type', ('type',
models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')], models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')],
max_length=2, verbose_name='Login type')), max_length=2, verbose_name='Login type')),
('ip', models.GenericIPAddressField(verbose_name='Login ip')), ('ip', models.GenericIPAddressField(verbose_name='Login IP')),
('city', models.CharField(blank=True, max_length=254, null=True, ('city', models.CharField(blank=True, max_length=254, null=True,
verbose_name='Login city')), verbose_name='Login city')),
('user_agent', ('user_agent',

View File

@ -158,7 +158,7 @@ class UserLoginLog(models.Model):
type = models.CharField( type = models.CharField(
choices=LoginTypeChoices.choices, max_length=2, verbose_name=_("Login type") choices=LoginTypeChoices.choices, max_length=2, verbose_name=_("Login type")
) )
ip = models.GenericIPAddressField(verbose_name=_("Login ip")) ip = models.GenericIPAddressField(verbose_name=_("Login IP"))
city = models.CharField( city = models.CharField(
max_length=254, blank=True, null=True, verbose_name=_("Login city") max_length=254, blank=True, null=True, verbose_name=_("Login city")
) )

View File

@ -16,7 +16,7 @@ from rest_framework.response import Response
from common.api import JMSModelViewSet from common.api import JMSModelViewSet
from common.exceptions import JMSException from common.exceptions import JMSException
from common.utils import random_string, get_logger from common.utils import random_string, get_logger, get_request_ip
from common.utils.django import get_request_os from common.utils.django import get_request_os
from common.utils.http import is_true, is_false from common.utils.http import is_true, is_false
from orgs.mixins.api import RootOrgViewMixin from orgs.mixins.api import RootOrgViewMixin
@ -311,7 +311,9 @@ class ConnectionTokenViewSet(ExtraActionApiMixin, RootOrgViewMixin, JMSModelView
def _validate_acl(self, user, asset, account): def _validate_acl(self, user, asset, account):
from acls.models import LoginAssetACL from acls.models import LoginAssetACL
acl = LoginAssetACL.filter_queryset(user, asset, account).valid().first() acls = LoginAssetACL.filter_queryset(user, asset, account)
ip = get_request_ip(self.request)
acl = LoginAssetACL.get_match_rule_acls(user, ip, acls)
if not acl: if not acl:
return return
if acl.is_action(acl.ActionChoices.accept): if acl.is_action(acl.ActionChoices.accept):

View File

@ -340,15 +340,14 @@ class AuthACLMixin:
def _check_login_acl(self, user, ip): def _check_login_acl(self, user, ip):
# ACL 限制用户登录 # ACL 限制用户登录
acl = LoginACL.match(user, ip) acl = LoginACL.get_match_rule_acls(user, ip)
if not acl: if not acl:
return return
acl: LoginACL if acl.is_action(LoginACL.ActionChoices.accept):
if acl.is_action(acl.ActionChoices.accept):
return return
if acl.is_action(acl.ActionChoices.reject): if acl.is_action(LoginACL.ActionChoices.reject):
raise errors.LoginACLIPAndTimePeriodNotAllowed(user.username, request=self.request) raise errors.LoginACLIPAndTimePeriodNotAllowed(user.username, request=self.request)
if acl.is_action(acl.ActionChoices.review): if acl.is_action(acl.ActionChoices.review):

View File

@ -1,14 +1,16 @@
from common.utils.timezone import local_now from common.utils.timezone import local_now
def contains_time_period(time_periods): def contains_time_period(time_periods, ctime=None):
""" """
time_periods: [{"id": 1, "value": "00:00~07:30、10:00~13:00"}, {"id": 2, "value": "00:00~00:00"}] time_periods: [{"id": 1, "value": "00:00~07:30、10:00~13:00"}, {"id": 2, "value": "00:00~00:00"}]
""" """
if not time_periods: if not time_periods:
return False return None
current_time = local_now().strftime('%H:%M') if ctime is None:
ctime = local_now()
current_time = ctime.strftime('%H:%M')
today_time_period = next(filter(lambda x: str(x['id']) == local_now().strftime("%w"), time_periods)) today_time_period = next(filter(lambda x: str(x['id']) == local_now().strftime("%w"), time_periods))
today_time_period = today_time_period['value'] today_time_period = today_time_period['value']
if not today_time_period: if not today_time_period:

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:fc0862f2a9091f2e06602d6db26cfc9cc7a6b067012ec56b41ebc1e26d5072e9 oid sha256:8e5c8032359c81278ddea64227bd4492fb49ea6b48587e6a0f406824238d6d46
size 142045 size 141638

View File

@ -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-05-26 17:11+0800\n" "POT-Creation-Date: 2023-05-26 16:18+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"
@ -221,7 +221,7 @@ msgstr "ソース ID"
#: accounts/models/account.py:61 #: accounts/models/account.py:61
#: accounts/serializers/automations/change_secret.py:113 #: accounts/serializers/automations/change_secret.py:113
#: accounts/serializers/automations/change_secret.py:133 acls/models/base.py:59 #: accounts/serializers/automations/change_secret.py:133
#: acls/serializers/base.py:77 assets/serializers/asset/common.py:125 #: acls/serializers/base.py:77 assets/serializers/asset/common.py:125
#: assets/serializers/gateway.py:28 audits/models.py:49 ops/models/base.py:18 #: assets/serializers/gateway.py:28 audits/models.py:49 ops/models/base.py:18
#: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39
@ -820,6 +820,12 @@ msgstr "アクティブ"
msgid "Users" msgid "Users"
msgstr "ユーザー" msgstr "ユーザー"
#: acls/models/base.py:59 assets/models/automations/base.py:17
#: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:305
#: rbac/tree.py:35
msgid "Accounts"
msgstr "アカウント"
#: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60
#: ops/serializers/job.py:55 terminal/const.py:68 #: ops/serializers/job.py:55 terminal/const.py:68
#: terminal/models/session/session.py:43 terminal/serializers/command.py:18 #: terminal/models/session/session.py:43 terminal/serializers/command.py:18
@ -833,7 +839,7 @@ msgid "Regex"
msgstr "正規情報" msgstr "正規情報"
#: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79 #: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79
#: settings/serializers/basic.py:10 xpack/plugins/license/models.py:30 #: settings/serializers/basic.py:10 xpack/plugins/license/models.py:29
msgid "Content" msgid "Content"
msgstr "コンテンツ" msgstr "コンテンツ"
@ -876,10 +882,16 @@ msgid "Login confirm"
msgstr "ログイン確認" msgstr "ログイン確認"
#: acls/models/login_asset_acl.py:8 #: acls/models/login_asset_acl.py:8
#, fuzzy
#| msgid "User ID"
msgid "User IP"
msgstr "ユーザーID"
#: acls/models/login_asset_acl.py:11
msgid "Login asset acl" msgid "Login asset acl"
msgstr "ログインasset acl" msgstr "ログインasset acl"
#: acls/models/login_asset_acl.py:18 tickets/const.py:12 #: acls/models/login_asset_acl.py:21 tickets/const.py:12
msgid "Login asset confirm" msgid "Login asset confirm"
msgstr "ログイン資産の確認" msgstr "ログイン資産の確認"
@ -917,6 +929,11 @@ msgstr "いずれのレビューアも組織 '{}' に属していません"
msgid "Command group amount" msgid "Command group amount"
msgstr "コマンドグループ数" msgstr "コマンドグループ数"
#: acls/serializers/login_asset_acl.py:12 audits/models.py:161
#: tickets/models/ticket/login_confirm.py:10
msgid "Login IP"
msgstr "ログインIP"
#: acls/serializers/rules/rules.py:20 #: acls/serializers/rules/rules.py:20
#: xpack/plugins/cloud/serializers/task.py:22 #: xpack/plugins/cloud/serializers/task.py:22
msgid "IP address invalid: `{}`" msgid "IP address invalid: `{}`"
@ -1251,7 +1268,7 @@ msgstr "アドレス"
#: assets/models/asset/common.py:151 assets/models/platform.py:112 #: assets/models/asset/common.py:151 assets/models/platform.py:112
#: authentication/serializers/connect_token_secret.py:115 #: authentication/serializers/connect_token_secret.py:115
#: perms/serializers/user_permission.py:24 #: perms/serializers/user_permission.py:24
#: xpack/plugins/cloud/serializers/account_attrs.py:196 #: xpack/plugins/cloud/serializers/account_attrs.py:187
msgid "Platform" msgid "Platform"
msgstr "プラットフォーム" msgstr "プラットフォーム"
@ -1331,11 +1348,6 @@ msgstr "パスワードセレクター"
msgid "Submit selector" msgid "Submit selector"
msgstr "ボタンセレクターを確認する" msgstr "ボタンセレクターを確認する"
#: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38
#: assets/serializers/asset/common.py:305 rbac/tree.py:35
msgid "Accounts"
msgstr "アカウント"
#: assets/models/automations/base.py:22 ops/models/job.py:187 #: assets/models/automations/base.py:22 ops/models/job.py:187
#: settings/serializers/auth/sms.py:100 #: settings/serializers/auth/sms.py:100
msgid "Parameters" msgid "Parameters"
@ -2004,10 +2016,6 @@ msgstr "パスワード変更ログ"
msgid "Login type" msgid "Login type"
msgstr "ログインタイプ" msgstr "ログインタイプ"
#: audits/models.py:161 tickets/models/ticket/login_confirm.py:10
msgid "Login ip"
msgstr "ログインIP"
#: audits/models.py:163 #: audits/models.py:163
#: authentication/templates/authentication/_msg_different_city.html:11 #: authentication/templates/authentication/_msg_different_city.html:11
#: tickets/models/ticket/login_confirm.py:11 #: tickets/models/ticket/login_confirm.py:11
@ -4606,7 +4614,7 @@ msgid "SSO auth key TTL"
msgstr "Token有効期間" msgstr "Token有効期間"
#: settings/serializers/auth/sso.py:17 #: settings/serializers/auth/sso.py:17
#: xpack/plugins/cloud/serializers/account_attrs.py:193 #: xpack/plugins/cloud/serializers/account_attrs.py:184
msgid "Unit: second" msgid "Unit: second"
msgstr "単位: 秒" msgstr "単位: 秒"
@ -5750,7 +5758,7 @@ msgid "Redis port"
msgstr "Redis ポート" msgstr "Redis ポート"
#: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:29
#: terminal/models/component/endpoint.py:98 terminal/serializers/endpoint.py:71 #: terminal/models/component/endpoint.py:98 terminal/serializers/endpoint.py:68
#: terminal/serializers/storage.py:38 terminal/serializers/storage.py:50 #: terminal/serializers/storage.py:38 terminal/serializers/storage.py:50
#: terminal/serializers/storage.py:80 terminal/serializers/storage.py:90 #: terminal/serializers/storage.py:80 terminal/serializers/storage.py:90
#: terminal/serializers/storage.py:98 #: terminal/serializers/storage.py:98
@ -6051,11 +6059,21 @@ msgstr ""
#: terminal/serializers/endpoint.py:64 #: terminal/serializers/endpoint.py:64
msgid "" msgid ""
"The assets within this IP range, the following endpoint will be used for the "
"connection"
msgstr "このIP範囲内のアセットは、以下のエンドポイントを使用して接続されます"
#: terminal/serializers/endpoint.py:60
msgid ""
"If asset IP addresses under different endpoints conflict, use asset labels" "If asset IP addresses under different endpoints conflict, use asset labels"
msgstr "" msgstr ""
"異なるエンドポイントの下に競合するアセットIPがある場合は、アセットタグを使用" "異なるエンドポイントの下に競合するアセットIPがある場合は、アセットタグを使用"
"して実装します" "して実装します"
#: terminal/serializers/endpoint.py:64
msgid "Asset IP"
msgstr "資産 IP"
#: terminal/serializers/session.py:24 terminal/serializers/session.py:46 #: terminal/serializers/session.py:24 terminal/serializers/session.py:46
msgid "Can replay" msgid "Can replay"
msgstr "再生できます" msgstr "再生できます"
@ -7248,7 +7266,7 @@ msgstr "クラウドアカウント"
msgid "Test cloud account" msgid "Test cloud account"
msgstr "クラウドアカウントのテスト" msgstr "クラウドアカウントのテスト"
#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:36 #: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:37
msgid "Regions" msgid "Regions"
msgstr "リージョン" msgstr "リージョン"
@ -7256,15 +7274,15 @@ msgstr "リージョン"
msgid "Hostname strategy" msgid "Hostname strategy"
msgstr "ホスト名戦略" msgstr "ホスト名戦略"
#: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:39 #: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:40
msgid "IP network segment group" msgid "IP network segment group"
msgstr "IPネットワークセグメントグループ" msgstr "IPネットワークセグメントグループ"
#: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:44 #: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:45
msgid "Sync IP type" msgid "Sync IP type"
msgstr "同期IPタイプ" msgstr "同期IPタイプ"
#: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:61 #: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:62
msgid "Always update" msgid "Always update"
msgstr "常に更新" msgstr "常に更新"
@ -7549,11 +7567,15 @@ msgstr "ファイルはJSON形式です。"
msgid "IP address invalid `{}`, {}" msgid "IP address invalid `{}`, {}"
msgstr "IPアドレスが無効: '{}', {}" msgstr "IPアドレスが無効: '{}', {}"
#: xpack/plugins/cloud/serializers/account_attrs.py:172 #: xpack/plugins/cloud/serializers/account_attrs.py:162
msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255" #, fuzzy
#| msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255"
msgid ""
"Format for comma-delimited string,Such as: 192.168.1.0/24, "
"10.0.0.0-10.0.0.255"
msgstr "例192.168.1.0/24,10.0.0.0-10.0.0.255" msgstr "例192.168.1.0/24,10.0.0.0-10.0.0.255"
#: xpack/plugins/cloud/serializers/account_attrs.py:175 #: xpack/plugins/cloud/serializers/account_attrs.py:166
msgid "" msgid ""
"The port is used to detect the validity of the IP address. When the " "The port is used to detect the validity of the IP address. When the "
"synchronization task is executed, only the valid IP address will be " "synchronization task is executed, only the valid IP address will be "
@ -7563,29 +7585,36 @@ msgstr ""
"実行されると、有効な IP アドレスのみが同期されます。 <br>ポートが0の場合、す" "実行されると、有効な IP アドレスのみが同期されます。 <br>ポートが0の場合、す"
"べてのIPアドレスが有効です。" "べてのIPアドレスが有効です。"
#: xpack/plugins/cloud/serializers/account_attrs.py:183 #: xpack/plugins/cloud/serializers/account_attrs.py:174
msgid "Hostname prefix" msgid "Hostname prefix"
msgstr "ホスト名プレフィックス" msgstr "ホスト名プレフィックス"
#: xpack/plugins/cloud/serializers/account_attrs.py:186 #: xpack/plugins/cloud/serializers/account_attrs.py:177
msgid "IP segment" msgid "IP segment"
msgstr "IP セグメント" msgstr "IP セグメント"
#: xpack/plugins/cloud/serializers/account_attrs.py:190 #: xpack/plugins/cloud/serializers/account_attrs.py:181
msgid "Test port" msgid "Test port"
msgstr "テストポート" msgstr "テストポート"
#: xpack/plugins/cloud/serializers/account_attrs.py:193 #: xpack/plugins/cloud/serializers/account_attrs.py:184
msgid "Test timeout" msgid "Test timeout"
msgstr "テストタイムアウト" msgstr "テストタイムアウト"
#: xpack/plugins/cloud/serializers/task.py:28 #: xpack/plugins/cloud/serializers/task.py:28
#, fuzzy
#| msgid ""
#| "Only instances matching the IP range will be synced. <br>If the instance "
#| "contains multiple IP addresses, the first IP address that matches will be "
#| "used as the IP for the created asset. <br>The default value of * means "
#| "sync all instances and randomly match IP addresses. <br>Such as: "
#| "192.168.1.0/24, 10.1.1.1-10.1.1.20"
msgid "" msgid ""
"Only instances matching the IP range will be synced. <br>If the instance " "Only instances matching the IP range will be synced. <br>If the instance "
"contains multiple IP addresses, the first IP address that matches will be " "contains multiple IP addresses, the first IP address that matches will be "
"used as the IP for the created asset. <br>The default value of * means sync " "used as the IP for the created asset. <br>The default value of * means sync "
"all instances and randomly match IP addresses. <br>Such as: 192.168.1.0/24, " "all instances and randomly match IP addresses. <br>Format for comma-"
"10.1.1.1-10.1.1.20" "delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20"
msgstr "" msgstr ""
"IP範囲に一致するインスタンスのみが同期されます。<br>インスタンスに複数のIPア" "IP範囲に一致するインスタンスのみが同期されます。<br>インスタンスに複数のIPア"
"ドレスが含まれている場合、一致する最初のIPアドレスが作成されたアセットのIPと" "ドレスが含まれている場合、一致する最初のIPアドレスが作成されたアセットのIPと"
@ -7593,11 +7622,11 @@ msgstr ""
"ドレスをランダムに一致させることを意味します。 <br>例:" "ドレスをランダムに一致させることを意味します。 <br>例:"
"192.168.1.0/24,10.1.1.1-10.1.1.20" "192.168.1.0/24,10.1.1.1-10.1.1.20"
#: xpack/plugins/cloud/serializers/task.py:34 #: xpack/plugins/cloud/serializers/task.py:35
msgid "History count" msgid "History count"
msgstr "実行回数" msgstr "実行回数"
#: xpack/plugins/cloud/serializers/task.py:35 #: xpack/plugins/cloud/serializers/task.py:36
msgid "Instance count" msgid "Instance count"
msgstr "インスタンス数" msgstr "インスタンス数"
@ -7657,23 +7686,23 @@ msgstr "ライセンスのインポートに成功"
msgid "License is invalid" msgid "License is invalid"
msgstr "ライセンスが無効です" msgstr "ライセンスが無効です"
#: xpack/plugins/license/meta.py:11 xpack/plugins/license/models.py:138 #: xpack/plugins/license/meta.py:11 xpack/plugins/license/models.py:135
msgid "License" msgid "License"
msgstr "ライセンス" msgstr "ライセンス"
#: xpack/plugins/license/models.py:80 #: xpack/plugins/license/models.py:79
msgid "Standard edition" msgid "Standard edition"
msgstr "標準版" msgstr "標準版"
#: xpack/plugins/license/models.py:82 #: xpack/plugins/license/models.py:81
msgid "Enterprise edition" msgid "Enterprise edition"
msgstr "エンタープライズ版" msgstr "エンタープライズ版"
#: xpack/plugins/license/models.py:84 #: xpack/plugins/license/models.py:83
msgid "Ultimate edition" msgid "Ultimate edition"
msgstr "究極のエディション" msgstr "究極のエディション"
#: xpack/plugins/license/models.py:86 #: xpack/plugins/license/models.py:85
msgid "Community edition" msgid "Community edition"
msgstr "コミュニティ版" msgstr "コミュニティ版"

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:1fabd2ec950291422c14b66af097bd73cce52bbc4b7913c1b9ea732eee855901 oid sha256:f4cf57efef290fb80f5159a628b8cde7861cb2bd3fcc247fcf7255fbd2757fb9
size 116210 size 115892

View File

@ -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-05-26 17:11+0800\n" "POT-Creation-Date: 2023-05-26 16:18+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"
@ -220,7 +220,7 @@ msgstr "来源 ID"
#: accounts/models/account.py:61 #: accounts/models/account.py:61
#: accounts/serializers/automations/change_secret.py:113 #: accounts/serializers/automations/change_secret.py:113
#: accounts/serializers/automations/change_secret.py:133 acls/models/base.py:59 #: accounts/serializers/automations/change_secret.py:133
#: acls/serializers/base.py:77 assets/serializers/asset/common.py:125 #: acls/serializers/base.py:77 assets/serializers/asset/common.py:125
#: assets/serializers/gateway.py:28 audits/models.py:49 ops/models/base.py:18 #: assets/serializers/gateway.py:28 audits/models.py:49 ops/models/base.py:18
#: perms/models/asset_permission.py:70 perms/serializers/permission.py:39 #: perms/models/asset_permission.py:70 perms/serializers/permission.py:39
@ -816,6 +816,12 @@ msgstr "激活中"
msgid "Users" msgid "Users"
msgstr "用户管理" msgstr "用户管理"
#: acls/models/base.py:59 assets/models/automations/base.py:17
#: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:305
#: rbac/tree.py:35
msgid "Accounts"
msgstr "账号管理"
#: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60
#: ops/serializers/job.py:55 terminal/const.py:68 #: ops/serializers/job.py:55 terminal/const.py:68
#: terminal/models/session/session.py:43 terminal/serializers/command.py:18 #: terminal/models/session/session.py:43 terminal/serializers/command.py:18
@ -829,7 +835,7 @@ msgid "Regex"
msgstr "正则表达式" msgstr "正则表达式"
#: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79 #: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79
#: settings/serializers/basic.py:10 xpack/plugins/license/models.py:30 #: settings/serializers/basic.py:10 xpack/plugins/license/models.py:29
msgid "Content" msgid "Content"
msgstr "内容" msgstr "内容"
@ -872,10 +878,16 @@ msgid "Login confirm"
msgstr "登录复核" msgstr "登录复核"
#: acls/models/login_asset_acl.py:8 #: acls/models/login_asset_acl.py:8
#, fuzzy
#| msgid "User ID"
msgid "User IP"
msgstr "用户 ID"
#: acls/models/login_asset_acl.py:11
msgid "Login asset acl" msgid "Login asset acl"
msgstr "登录资产访问控制" msgstr "登录资产访问控制"
#: acls/models/login_asset_acl.py:18 tickets/const.py:12 #: acls/models/login_asset_acl.py:21 tickets/const.py:12
msgid "Login asset confirm" msgid "Login asset confirm"
msgstr "登录资产复核" msgstr "登录资产复核"
@ -912,6 +924,11 @@ msgstr "所有复核人都不属于组织 `{}`"
msgid "Command group amount" msgid "Command group amount"
msgstr "命令组数量" msgstr "命令组数量"
#: acls/serializers/login_asset_acl.py:12 audits/models.py:161
#: tickets/models/ticket/login_confirm.py:10
msgid "Login IP"
msgstr "登录 IP"
#: acls/serializers/rules/rules.py:20 #: acls/serializers/rules/rules.py:20
#: xpack/plugins/cloud/serializers/task.py:22 #: xpack/plugins/cloud/serializers/task.py:22
msgid "IP address invalid: `{}`" msgid "IP address invalid: `{}`"
@ -929,7 +946,7 @@ msgstr ""
#: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_oauth_bind.html:12
#: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_password_success.html:8
#: authentication/templates/authentication/_msg_rest_public_key_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8
#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:67 #: settings/serializers/terminal.py:10
msgid "IP" msgid "IP"
msgstr "IP" msgstr "IP"
@ -1244,7 +1261,7 @@ msgstr "地址"
#: assets/models/asset/common.py:151 assets/models/platform.py:112 #: assets/models/asset/common.py:151 assets/models/platform.py:112
#: authentication/serializers/connect_token_secret.py:115 #: authentication/serializers/connect_token_secret.py:115
#: perms/serializers/user_permission.py:24 #: perms/serializers/user_permission.py:24
#: xpack/plugins/cloud/serializers/account_attrs.py:196 #: xpack/plugins/cloud/serializers/account_attrs.py:187
msgid "Platform" msgid "Platform"
msgstr "系统平台" msgstr "系统平台"
@ -1324,11 +1341,6 @@ msgstr "密码选择器"
msgid "Submit selector" msgid "Submit selector"
msgstr "确认按钮选择器" msgstr "确认按钮选择器"
#: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38
#: assets/serializers/asset/common.py:305 rbac/tree.py:35
msgid "Accounts"
msgstr "账号管理"
#: assets/models/automations/base.py:22 ops/models/job.py:187 #: assets/models/automations/base.py:22 ops/models/job.py:187
#: settings/serializers/auth/sms.py:100 #: settings/serializers/auth/sms.py:100
msgid "Parameters" msgid "Parameters"
@ -1993,10 +2005,6 @@ msgstr "改密日志"
msgid "Login type" msgid "Login type"
msgstr "登录方式" msgstr "登录方式"
#: audits/models.py:161 tickets/models/ticket/login_confirm.py:10
msgid "Login ip"
msgstr "登录IP"
#: audits/models.py:163 #: audits/models.py:163
#: authentication/templates/authentication/_msg_different_city.html:11 #: authentication/templates/authentication/_msg_different_city.html:11
#: tickets/models/ticket/login_confirm.py:11 #: tickets/models/ticket/login_confirm.py:11
@ -4562,7 +4570,7 @@ msgid "SSO auth key TTL"
msgstr "令牌有效期" msgstr "令牌有效期"
#: settings/serializers/auth/sso.py:17 #: settings/serializers/auth/sso.py:17
#: xpack/plugins/cloud/serializers/account_attrs.py:193 #: xpack/plugins/cloud/serializers/account_attrs.py:184
msgid "Unit: second" msgid "Unit: second"
msgstr "单位: 秒" msgstr "单位: 秒"
@ -5669,7 +5677,7 @@ msgid "Redis port"
msgstr "Redis 端口" msgstr "Redis 端口"
#: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:29
#: terminal/models/component/endpoint.py:98 terminal/serializers/endpoint.py:71 #: terminal/models/component/endpoint.py:98 terminal/serializers/endpoint.py:68
#: terminal/serializers/storage.py:38 terminal/serializers/storage.py:50 #: terminal/serializers/storage.py:38 terminal/serializers/storage.py:50
#: terminal/serializers/storage.py:80 terminal/serializers/storage.py:90 #: terminal/serializers/storage.py:80 terminal/serializers/storage.py:90
#: terminal/serializers/storage.py:98 #: terminal/serializers/storage.py:98
@ -5967,9 +5975,19 @@ msgstr ""
#: terminal/serializers/endpoint.py:64 #: terminal/serializers/endpoint.py:64
msgid "" msgid ""
"The assets within this IP range, the following endpoint will be used for the "
"connection"
msgstr "该 IP 范围内的资产,将使用下面的端点进行连接"
#: terminal/serializers/endpoint.py:60
msgid ""
"If asset IP addresses under different endpoints conflict, use asset labels" "If asset IP addresses under different endpoints conflict, use asset labels"
msgstr "如果不同端点下的资产 IP 有冲突,使用资产标签实现" msgstr "如果不同端点下的资产 IP 有冲突,使用资产标签实现"
#: terminal/serializers/endpoint.py:64
msgid "Asset IP"
msgstr "资产 IP"
#: terminal/serializers/session.py:24 terminal/serializers/session.py:46 #: terminal/serializers/session.py:24 terminal/serializers/session.py:46
msgid "Can replay" msgid "Can replay"
msgstr "是否可重放" msgstr "是否可重放"
@ -7143,7 +7161,7 @@ msgstr "云账号"
msgid "Test cloud account" msgid "Test cloud account"
msgstr "测试云账号" msgstr "测试云账号"
#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:36 #: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:37
msgid "Regions" msgid "Regions"
msgstr "地域" msgstr "地域"
@ -7151,15 +7169,15 @@ msgstr "地域"
msgid "Hostname strategy" msgid "Hostname strategy"
msgstr "主机名策略" msgstr "主机名策略"
#: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:39 #: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:40
msgid "IP network segment group" msgid "IP network segment group"
msgstr "IP网段组" msgstr "IP网段组"
#: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:44 #: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:45
msgid "Sync IP type" msgid "Sync IP type"
msgstr "同步IP类型" msgstr "同步IP类型"
#: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:61 #: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:62
msgid "Always update" msgid "Always update"
msgstr "总是更新" msgstr "总是更新"
@ -7444,11 +7462,15 @@ msgstr "JSON 格式的文件"
msgid "IP address invalid `{}`, {}" msgid "IP address invalid `{}`, {}"
msgstr "IP 地址无效: `{}`, {}" msgstr "IP 地址无效: `{}`, {}"
#: xpack/plugins/cloud/serializers/account_attrs.py:172 #: xpack/plugins/cloud/serializers/account_attrs.py:162
msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255" #, fuzzy
#| msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255"
msgid ""
"Format for comma-delimited string,Such as: 192.168.1.0/24, "
"10.0.0.0-10.0.0.255"
msgstr "如192.168.1.0/24,10.0.0.0-10.0.0.255" msgstr "如192.168.1.0/24,10.0.0.0-10.0.0.255"
#: xpack/plugins/cloud/serializers/account_attrs.py:175 #: xpack/plugins/cloud/serializers/account_attrs.py:166
msgid "" msgid ""
"The port is used to detect the validity of the IP address. When the " "The port is used to detect the validity of the IP address. When the "
"synchronization task is executed, only the valid IP address will be " "synchronization task is executed, only the valid IP address will be "
@ -7457,39 +7479,46 @@ msgstr ""
"端口用来检测 IP 地址的有效性,在同步任务执行时,只会同步有效的 IP 地址。 <br>" "端口用来检测 IP 地址的有效性,在同步任务执行时,只会同步有效的 IP 地址。 <br>"
"如果端口为 0则表示所有 IP 地址均有效。" "如果端口为 0则表示所有 IP 地址均有效。"
#: xpack/plugins/cloud/serializers/account_attrs.py:183 #: xpack/plugins/cloud/serializers/account_attrs.py:174
msgid "Hostname prefix" msgid "Hostname prefix"
msgstr "主机名前缀" msgstr "主机名前缀"
#: xpack/plugins/cloud/serializers/account_attrs.py:186 #: xpack/plugins/cloud/serializers/account_attrs.py:177
msgid "IP segment" msgid "IP segment"
msgstr "IP 网段" msgstr "IP 网段"
#: xpack/plugins/cloud/serializers/account_attrs.py:190 #: xpack/plugins/cloud/serializers/account_attrs.py:181
msgid "Test port" msgid "Test port"
msgstr "测试端口" msgstr "测试端口"
#: xpack/plugins/cloud/serializers/account_attrs.py:193 #: xpack/plugins/cloud/serializers/account_attrs.py:184
msgid "Test timeout" msgid "Test timeout"
msgstr "测试超时时间" msgstr "测试超时时间"
#: xpack/plugins/cloud/serializers/task.py:28 #: xpack/plugins/cloud/serializers/task.py:28
#, fuzzy
#| msgid ""
#| "Only instances matching the IP range will be synced. <br>If the instance "
#| "contains multiple IP addresses, the first IP address that matches will be "
#| "used as the IP for the created asset. <br>The default value of * means "
#| "sync all instances and randomly match IP addresses. <br>Such as: "
#| "192.168.1.0/24, 10.1.1.1-10.1.1.20"
msgid "" msgid ""
"Only instances matching the IP range will be synced. <br>If the instance " "Only instances matching the IP range will be synced. <br>If the instance "
"contains multiple IP addresses, the first IP address that matches will be " "contains multiple IP addresses, the first IP address that matches will be "
"used as the IP for the created asset. <br>The default value of * means sync " "used as the IP for the created asset. <br>The default value of * means sync "
"all instances and randomly match IP addresses. <br>Such as: 192.168.1.0/24, " "all instances and randomly match IP addresses. <br>Format for comma-"
"10.1.1.1-10.1.1.20" "delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20"
msgstr "" msgstr ""
"只有匹配到 IP 段的实例会被同步。<br>如果实例包含多个 IP 地址,那么第一个匹配" "只有匹配到 IP 段的实例会被同步。<br>如果实例包含多个 IP 地址,那么第一个匹配"
"到的 IP 地址将被用作创建的资产的 IP。<br>默认值 * 表示同步所有实例和随机匹配 " "到的 IP 地址将被用作创建的资产的 IP。<br>默认值 * 表示同步所有实例和随机匹配 "
"IP 地址。<br>例如:192.168.1.0/24,10.1.1.1-10.1.1.20" "IP 地址。<br>例如:192.168.1.0/24,10.1.1.1-10.1.1.20"
#: xpack/plugins/cloud/serializers/task.py:34 #: xpack/plugins/cloud/serializers/task.py:35
msgid "History count" msgid "History count"
msgstr "执行次数" msgstr "执行次数"
#: xpack/plugins/cloud/serializers/task.py:35 #: xpack/plugins/cloud/serializers/task.py:36
msgid "Instance count" msgid "Instance count"
msgstr "实例个数" msgstr "实例个数"
@ -7549,23 +7578,23 @@ msgstr "许可证导入成功"
msgid "License is invalid" msgid "License is invalid"
msgstr "无效的许可证" msgstr "无效的许可证"
#: xpack/plugins/license/meta.py:11 xpack/plugins/license/models.py:138 #: xpack/plugins/license/meta.py:11 xpack/plugins/license/models.py:135
msgid "License" msgid "License"
msgstr "许可证" msgstr "许可证"
#: xpack/plugins/license/models.py:80 #: xpack/plugins/license/models.py:79
msgid "Standard edition" msgid "Standard edition"
msgstr "标准版" msgstr "标准版"
#: xpack/plugins/license/models.py:82 #: xpack/plugins/license/models.py:81
msgid "Enterprise edition" msgid "Enterprise edition"
msgstr "企业版" msgstr "企业版"
#: xpack/plugins/license/models.py:84 #: xpack/plugins/license/models.py:83
msgid "Ultimate edition" msgid "Ultimate edition"
msgstr "旗舰版" msgstr "旗舰版"
#: xpack/plugins/license/models.py:86 #: xpack/plugins/license/models.py:85
msgid "Community edition" msgid "Community edition"
msgstr "社区版" msgstr "社区版"

View File

@ -1,4 +1,4 @@
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import gettext_lazy as _
from rest_framework import serializers from rest_framework import serializers
from acls.serializers.rules import ip_group_child_validator, ip_group_help_text from acls.serializers.rules import ip_group_child_validator, ip_group_help_text
@ -17,7 +17,8 @@ class EndpointSerializer(BulkModelSerializer):
max_length=128, default=db_port_manager.oracle_port_range, read_only=True, max_length=128, default=db_port_manager.oracle_port_range, read_only=True,
label=_('Oracle port range'), label=_('Oracle port range'),
help_text=_( help_text=_(
'Oracle proxy server listen port is dynamic, Each additional Oracle database instance adds a port listener' 'Oracle proxy server listen port is dynamic, Each additional Oracle '
'database instance adds a port listener'
) )
) )
@ -59,12 +60,13 @@ class EndpointSerializer(BulkModelSerializer):
class EndpointRuleSerializer(BulkModelSerializer): class EndpointRuleSerializer(BulkModelSerializer):
_ip_group_help_text = '{} <br> {}'.format( _ip_group_help_text = '{}, {} <br>{}'.format(
_('The assets within this IP range, the following endpoint will be used for the connection'),
_('If asset IP addresses under different endpoints conflict, use asset labels'),
ip_group_help_text, ip_group_help_text,
_('If asset IP addresses under different endpoints conflict, use asset labels')
) )
ip_group = serializers.ListField( ip_group = serializers.ListField(
default=['*'], label=_('IP'), help_text=_ip_group_help_text, default=['*'], label=_('Asset IP'), help_text=_ip_group_help_text,
child=serializers.CharField(max_length=1024, validators=[ip_group_child_validator]) child=serializers.CharField(max_length=1024, validators=[ip_group_child_validator])
) )
endpoint = ObjectRelatedField( endpoint = ObjectRelatedField(
@ -80,4 +82,5 @@ class EndpointRuleSerializer(BulkModelSerializer):
'comment', 'date_created', 'date_updated', 'created_by' 'comment', 'date_created', 'date_updated', 'created_by'
] ]
extra_kwargs = { extra_kwargs = {
'priority': {'default': 50}
} }

View File

@ -1,8 +1,8 @@
# Generated by Django 3.1.14 on 2022-06-09 09:58 # Generated by Django 3.1.14 on 2022-06-09 09:58
import django.db.models.deletion
from django.conf import settings from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -21,7 +21,7 @@ class Migration(migrations.Migration):
('ticket_ptr', ('ticket_ptr',
models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True,
primary_key=True, serialize=False, to='tickets.ticket')), primary_key=True, serialize=False, to='tickets.ticket')),
('apply_login_ip', models.GenericIPAddressField(null=True, verbose_name='Login ip')), ('apply_login_ip', models.GenericIPAddressField(null=True, verbose_name='Login IP')),
('apply_login_city', models.CharField(max_length=64, null=True, verbose_name='Login city')), ('apply_login_city', models.CharField(max_length=64, null=True, verbose_name='Login city')),
('apply_login_datetime', models.DateTimeField(null=True, verbose_name='Login datetime')), ('apply_login_datetime', models.DateTimeField(null=True, verbose_name='Login datetime')),
], ],

View File

@ -12,7 +12,7 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='applyassetticket', model_name='applyassetticket',
name='apply_actions', name='apply_actions',
field=models.IntegerField(default=31, verbose_name='Actions'), field=models.IntegerField(default=1, verbose_name='Actions'),
), ),
migrations.AlterField( migrations.AlterField(
model_name='approvalrule', model_name='approvalrule',

View File

@ -15,7 +15,7 @@ class ApplyAssetTicket(Ticket):
# 申请信息 # 申请信息
apply_assets = models.ManyToManyField('assets.Asset', verbose_name=_('Asset')) apply_assets = models.ManyToManyField('assets.Asset', verbose_name=_('Asset'))
apply_accounts = models.JSONField(default=list, verbose_name=_('Apply accounts')) apply_accounts = models.JSONField(default=list, verbose_name=_('Apply accounts'))
apply_actions = models.IntegerField(verbose_name=_('Actions'), default=ActionChoices.all()) apply_actions = models.IntegerField(verbose_name=_('Actions'), default=ActionChoices.connect)
apply_date_start = models.DateTimeField(verbose_name=_('Date start'), null=True) apply_date_start = models.DateTimeField(verbose_name=_('Date start'), null=True)
apply_date_expired = models.DateTimeField(verbose_name=_('Date expired'), null=True) apply_date_expired = models.DateTimeField(verbose_name=_('Date expired'), null=True)

View File

@ -7,6 +7,6 @@ __all__ = ['ApplyLoginTicket']
class ApplyLoginTicket(Ticket): class ApplyLoginTicket(Ticket):
apply_login_ip = models.GenericIPAddressField(verbose_name=_('Login ip'), null=True) apply_login_ip = models.GenericIPAddressField(verbose_name=_('Login IP'), null=True)
apply_login_city = models.CharField(max_length=64, verbose_name=_('Login city'), null=True) apply_login_city = models.CharField(max_length=64, verbose_name=_('Login city'), null=True)
apply_login_datetime = models.DateTimeField(verbose_name=_('Login datetime'), null=True) apply_login_datetime = models.DateTimeField(verbose_name=_('Login datetime'), null=True)

View File

@ -97,7 +97,7 @@ class Migration(migrations.Migration):
('username', models.CharField(max_length=20, verbose_name='Username')), ('username', models.CharField(max_length=20, verbose_name='Username')),
('type', ('type',
models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')], max_length=2, verbose_name='Login type')), models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')], max_length=2, verbose_name='Login type')),
('ip', models.GenericIPAddressField(verbose_name='Login ip')), ('ip', models.GenericIPAddressField(verbose_name='Login IP')),
('city', models.CharField(blank=True, max_length=254, null=True, verbose_name='Login city')), ('city', models.CharField(blank=True, max_length=254, null=True, verbose_name='Login city')),
('user_agent', models.CharField(blank=True, max_length=254, null=True, verbose_name='User agent')), ('user_agent', models.CharField(blank=True, max_length=254, null=True, verbose_name='User agent')),
('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date login')), ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date login')),