diff --git a/apps/accounts/api/account/__init__.py b/apps/accounts/api/account/__init__.py index f6d8376a6..7f90c23c7 100644 --- a/apps/accounts/api/account/__init__.py +++ b/apps/accounts/api/account/__init__.py @@ -1,3 +1,4 @@ from .account import * from .task import * from .template import * +from .virtual import * diff --git a/apps/accounts/api/account/virtual.py b/apps/accounts/api/account/virtual.py new file mode 100644 index 000000000..79dec3f78 --- /dev/null +++ b/apps/accounts/api/account/virtual.py @@ -0,0 +1,20 @@ +from django.shortcuts import get_object_or_404 + +from accounts.models import VirtualAccount +from accounts.serializers import VirtualAccountSerializer +from common.utils import is_uuid +from orgs.mixins.api import OrgBulkModelViewSet + + +class VirtualAccountViewSet(OrgBulkModelViewSet): + serializer_class = VirtualAccountSerializer + search_fields = ('alias',) + filterset_fields = ('alias',) + + def get_queryset(self): + return VirtualAccount.get_or_init_queryset() + + def get_object(self, ): + pk = self.kwargs.get('pk') + kwargs = {'pk': pk} if is_uuid(pk) else {'alias': pk} + return get_object_or_404(VirtualAccount, **kwargs) diff --git a/apps/accounts/const/account.py b/apps/accounts/const/account.py index 44caa2889..b1d3e348e 100644 --- a/apps/accounts/const/account.py +++ b/apps/accounts/const/account.py @@ -16,6 +16,10 @@ class AliasAccount(TextChoices): USER = '@USER', _('Dynamic user') ANON = '@ANON', _('Anonymous account') + @classmethod + def virtual_choices(cls): + return [(k, v) for k, v in cls.choices if k not in (cls.ALL,)] + class Source(TextChoices): LOCAL = 'local', _('Local') diff --git a/apps/accounts/const/vault.py b/apps/accounts/const/vault.py index 1da2a591b..1e41b6d86 100644 --- a/apps/accounts/const/vault.py +++ b/apps/accounts/const/vault.py @@ -5,5 +5,5 @@ __all__ = ['VaultTypeChoices'] class VaultTypeChoices(models.TextChoices): - local = 'local', _('Local Vault') + local = 'local', _('Database') hcp = 'hcp', _('HCP Vault') diff --git a/apps/accounts/migrations/0013_virtualaccount.py b/apps/accounts/migrations/0013_virtualaccount.py new file mode 100644 index 000000000..9b3b02b7c --- /dev/null +++ b/apps/accounts/migrations/0013_virtualaccount.py @@ -0,0 +1,30 @@ +# Generated by Django 4.1.10 on 2023-08-01 09:12 + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + dependencies = [ + ('accounts', '0012_auto_20230621_1456'), + ] + + operations = [ + migrations.CreateModel( + name='VirtualAccount', + fields=[ + ('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('alias', models.CharField(choices=[('@INPUT', 'Manual input'), ('@USER', 'Dynamic user'), ('@ANON', 'Anonymous account')], max_length=128, verbose_name='Alias')), + ('secret_from_login', models.BooleanField(default=None, null=True, verbose_name='Secret from login')), + ], + options={ + 'unique_together': {('alias', 'org_id')}, + }, + ), + ] diff --git a/apps/accounts/models/__init__.py b/apps/accounts/models/__init__.py index df686a50b..9a3b780c8 100644 --- a/apps/accounts/models/__init__.py +++ b/apps/accounts/models/__init__.py @@ -1,3 +1,5 @@ from .account import * from .automations import * from .base import * +from .template import * +from .virtual import * diff --git a/apps/accounts/models/account.py b/apps/accounts/models/account.py index 0f4077536..1bdf6e83d 100644 --- a/apps/accounts/models/account.py +++ b/apps/accounts/models/account.py @@ -1,6 +1,4 @@ from django.db import models -from django.db.models import Count, Q -from django.utils import timezone from django.utils.translation import gettext_lazy as _ from simple_history.models import HistoricalRecords @@ -8,9 +6,9 @@ from assets.models.base import AbsConnectivity from common.utils import lazyproperty from .base import BaseAccount from .mixins import VaultModelMixin -from ..const import AliasAccount, Source +from ..const import Source -__all__ = ['Account', 'AccountTemplate', 'AccountHistoricalRecords'] +__all__ = ['Account', 'AccountHistoricalRecords'] class AccountHistoricalRecords(HistoricalRecords): @@ -89,29 +87,6 @@ class Account(AbsConnectivity, BaseAccount): def has_secret(self): return bool(self.secret) - @classmethod - def get_special_account(cls, name): - if name == AliasAccount.INPUT.value: - return cls.get_manual_account() - elif name == AliasAccount.ANON.value: - return cls.get_anonymous_account() - else: - return cls(name=name, username=name, secret=None) - - @classmethod - def get_manual_account(cls): - """ @INPUT 手动登录的账号(any) """ - return cls(name=AliasAccount.INPUT.label, username=AliasAccount.INPUT.value, secret=None) - - @classmethod - def get_anonymous_account(cls): - return cls(name=AliasAccount.ANON.label, username=AliasAccount.ANON.value, secret=None) - - @classmethod - def get_user_account(cls): - """ @USER 动态用户的账号(self) """ - return cls(name=AliasAccount.USER.label, username=AliasAccount.USER.value, secret=None) - @lazyproperty def versions(self): return self.history.count() @@ -121,83 +96,6 @@ class Account(AbsConnectivity, BaseAccount): return self.asset.accounts.exclude(id=self.id).exclude(su_from=self) -class AccountTemplate(BaseAccount): - su_from = models.ForeignKey( - 'self', related_name='su_to', null=True, - on_delete=models.SET_NULL, verbose_name=_("Su from") - ) - - class Meta: - verbose_name = _('Account template') - unique_together = ( - ('name', 'org_id'), - ) - permissions = [ - ('view_accounttemplatesecret', _('Can view asset account template secret')), - ('change_accounttemplatesecret', _('Can change asset account template secret')), - ] - - @classmethod - def get_su_from_account_templates(cls, pk=None): - if pk is None: - return cls.objects.all() - return cls.objects.exclude(Q(id=pk) | Q(su_from_id=pk)) - - def __str__(self): - return f'{self.name}({self.username})' - - def get_su_from_account(self, asset): - su_from = self.su_from - if su_from and asset.platform.su_enabled: - account = asset.accounts.filter( - username=su_from.username, - secret_type=su_from.secret_type - ).first() - return account - - @staticmethod - def bulk_update_accounts(accounts, data): - history_model = Account.history.model - account_ids = accounts.values_list('id', flat=True) - history_accounts = history_model.objects.filter(id__in=account_ids) - account_id_count_map = { - str(i['id']): i['count'] - for i in history_accounts.values('id').order_by('id') - .annotate(count=Count(1)).values('id', 'count') - } - - for account in accounts: - account_id = str(account.id) - account.version = account_id_count_map.get(account_id) + 1 - for k, v in data.items(): - setattr(account, k, v) - Account.objects.bulk_update(accounts, ['version', 'secret']) - - @staticmethod - def bulk_create_history_accounts(accounts, user_id): - history_model = Account.history.model - history_account_objs = [] - for account in accounts: - history_account_objs.append( - history_model( - id=account.id, - version=account.version, - secret=account.secret, - secret_type=account.secret_type, - history_user_id=user_id, - history_date=timezone.now() - ) - ) - history_model.objects.bulk_create(history_account_objs) - - def bulk_sync_account_secret(self, accounts, user_id): - """ 批量同步账号密码 """ - if not accounts: - return - self.bulk_update_accounts(accounts, {'secret': self.secret}) - self.bulk_create_history_accounts(accounts, user_id) - - def replace_history_model_with_mixin(): """ 替换历史模型中的父类为指定的Mixin类。 diff --git a/apps/accounts/models/template.py b/apps/accounts/models/template.py new file mode 100644 index 000000000..adee261e6 --- /dev/null +++ b/apps/accounts/models/template.py @@ -0,0 +1,86 @@ +from django.db import models +from django.db.models import Count, Q +from django.utils import timezone +from django.utils.translation import gettext_lazy as _ + +from .account import Account +from .base import BaseAccount + +__all__ = ['AccountTemplate', ] + + +class AccountTemplate(BaseAccount): + su_from = models.ForeignKey( + 'self', related_name='su_to', null=True, + on_delete=models.SET_NULL, verbose_name=_("Su from") + ) + + class Meta: + verbose_name = _('Account template') + unique_together = ( + ('name', 'org_id'), + ) + permissions = [ + ('view_accounttemplatesecret', _('Can view asset account template secret')), + ('change_accounttemplatesecret', _('Can change asset account template secret')), + ] + + @classmethod + def get_su_from_account_templates(cls, pk=None): + if pk is None: + return cls.objects.all() + return cls.objects.exclude(Q(id=pk) | Q(su_from_id=pk)) + + def __str__(self): + return f'{self.name}({self.username})' + + def get_su_from_account(self, asset): + su_from = self.su_from + if su_from and asset.platform.su_enabled: + account = asset.accounts.filter( + username=su_from.username, + secret_type=su_from.secret_type + ).first() + return account + + @staticmethod + def bulk_update_accounts(accounts, data): + history_model = Account.history.model + account_ids = accounts.values_list('id', flat=True) + history_accounts = history_model.objects.filter(id__in=account_ids) + account_id_count_map = { + str(i['id']): i['count'] + for i in history_accounts.values('id').order_by('id') + .annotate(count=Count(1)).values('id', 'count') + } + + for account in accounts: + account_id = str(account.id) + account.version = account_id_count_map.get(account_id) + 1 + for k, v in data.items(): + setattr(account, k, v) + Account.objects.bulk_update(accounts, ['version', 'secret']) + + @staticmethod + def bulk_create_history_accounts(accounts, user_id): + history_model = Account.history.model + history_account_objs = [] + for account in accounts: + history_account_objs.append( + history_model( + id=account.id, + version=account.version, + secret=account.secret, + secret_type=account.secret_type, + history_user_id=user_id, + history_date=timezone.now() + ) + ) + history_model.objects.bulk_create(history_account_objs) + + def bulk_sync_account_secret(self, accounts, user_id): + """ 批量同步账号密码 """ + if not accounts: + return + self.bulk_update_accounts(accounts, {'secret': self.secret}) + self.bulk_create_history_accounts(accounts, user_id) diff --git a/apps/accounts/models/virtual.py b/apps/accounts/models/virtual.py new file mode 100644 index 000000000..88cf1b605 --- /dev/null +++ b/apps/accounts/models/virtual.py @@ -0,0 +1,103 @@ +from django.db import models +from django.utils.translation import gettext_lazy as _ + +from accounts.const import AliasAccount +from orgs.mixins.models import JMSOrgBaseModel + +__all__ = ['VirtualAccount'] + +from orgs.utils import tmp_to_org + + +class VirtualAccount(JMSOrgBaseModel): + alias = models.CharField(max_length=128, choices=AliasAccount.virtual_choices(), verbose_name=_('Alias'), ) + secret_from_login = models.BooleanField(default=None, null=True, verbose_name=_("Secret from login"), ) + + class Meta: + unique_together = [('alias', 'org_id')] + + @property + def name(self): + return self.get_alias_display() + + @property + def username(self): + usernames_map = { + AliasAccount.INPUT: _("Manual input"), + AliasAccount.USER: _("Same with user"), + AliasAccount.ANON: '' + } + usernames_map = {str(k): v for k, v in usernames_map.items()} + return usernames_map.get(self.alias, '') + + @property + def comment(self): + comments_map = { + AliasAccount.INPUT: _('Non-asset account, Input username/password on connect'), + AliasAccount.USER: _('The account username name same with user on connect'), + AliasAccount.ANON: _('Connect asset without using a username and password, ' + 'and it only supports web-based and custom-type assets'), + } + comments_map = {str(k): v for k, v in comments_map.items()} + return comments_map.get(self.alias, '') + + @classmethod + def get_or_init_queryset(cls): + aliases = [i[0] for i in AliasAccount.virtual_choices()] + alias_created = cls.objects.all().values_list('alias', flat=True) + need_created = set(aliases) - set(alias_created) + + if need_created: + accounts = [cls(alias=alias) for alias in need_created] + cls.objects.bulk_create(accounts, ignore_conflicts=True) + return cls.objects.all() + + @classmethod + def get_special_account(cls, alias, user, asset, input_username='', input_secret='', from_permed=True): + if alias == AliasAccount.INPUT.value: + account = cls.get_manual_account(input_username, input_secret, from_permed) + elif alias == AliasAccount.ANON.value: + account = cls.get_anonymous_account() + elif alias == AliasAccount.USER.value: + account = cls.get_same_account(user, asset, input_secret=input_secret, from_permed=from_permed) + else: + account = cls(name=alias, username=alias, secret=None) + account.alias = alias + if asset: + account.asset = asset + account.org_id = asset.org_id + return account + + @classmethod + def get_manual_account(cls, input_username='', input_secret='', from_permed=True): + """ @INPUT 手动登录的账号(any) """ + from .account import Account + if from_permed: + username = AliasAccount.INPUT.value + secret = '' + else: + username = input_username + secret = input_secret + return Account(name=AliasAccount.INPUT.label, username=username, secret=secret) + + @classmethod + def get_anonymous_account(cls): + from .account import Account + return Account(name=AliasAccount.ANON.label, username=AliasAccount.ANON.value, secret=None) + + @classmethod + def get_same_account(cls, user, asset, input_secret='', from_permed=True): + """ @USER 动态用户的账号(self) """ + from .account import Account + username = user.username + + with tmp_to_org(asset.org): + same_account = cls.objects.filter(alias='@USER').first() + + secret = '' + if same_account and same_account.secret_from_login: + secret = user.get_cached_password_if_has() + + if not secret and not from_permed: + secret = input_secret + return Account(name=AliasAccount.USER.label, username=username, secret=secret) diff --git a/apps/accounts/serializers/account/__init__.py b/apps/accounts/serializers/account/__init__.py index 2829931b2..207029047 100644 --- a/apps/accounts/serializers/account/__init__.py +++ b/apps/accounts/serializers/account/__init__.py @@ -1,5 +1,6 @@ from .account import * from .backup import * from .base import * -from .template import * from .gathered_account import * +from .template import * +from .virtual import * diff --git a/apps/accounts/serializers/account/virtual.py b/apps/accounts/serializers/account/virtual.py new file mode 100644 index 000000000..d4bd42589 --- /dev/null +++ b/apps/accounts/serializers/account/virtual.py @@ -0,0 +1,26 @@ +from django.utils.translation import gettext_lazy as _ +from rest_framework import serializers + +from accounts.models import VirtualAccount + +__all__ = ['VirtualAccountSerializer'] + + +class VirtualAccountSerializer(serializers.ModelSerializer): + class Meta: + model = VirtualAccount + field_mini = ['id', 'alias', 'username', 'name'] + common_fields = ['date_created', 'date_updated', 'comment'] + fields = field_mini + [ + 'secret_from_login', + ] + common_fields + read_only_fields = common_fields + common_fields + extra_kwargs = { + 'comment': {'label': _('Comment')}, + 'name': {'label': _('Name')}, + 'username': {'label': _('Username')}, + 'secret_from_login': {'help_text': _('Current only support login from AD/LDAP. Secret priority: ' + 'Same account in asset secret > Login secret > Manual input') + }, + 'alias': {'required': False}, + } diff --git a/apps/accounts/urls.py b/apps/accounts/urls.py index 94c8311e0..12d04274e 100644 --- a/apps/accounts/urls.py +++ b/apps/accounts/urls.py @@ -9,6 +9,7 @@ app_name = 'accounts' router = BulkRouter() router.register(r'accounts', api.AccountViewSet, 'account') +router.register(r'virtual-accounts', api.VirtualAccountViewSet, 'virtual-account') router.register(r'gathered-accounts', api.GatheredAccountViewSet, 'gathered-account') router.register(r'account-secrets', api.AccountSecretsViewSet, 'account-secret') router.register(r'account-templates', api.AccountTemplateViewSet, 'account-template') diff --git a/apps/authentication/api/access_key.py b/apps/authentication/api/access_key.py index bbda04c02..9253f449d 100644 --- a/apps/authentication/api/access_key.py +++ b/apps/authentication/api/access_key.py @@ -2,12 +2,13 @@ # from rest_framework.viewsets import ModelViewSet -from .. import serializers + from rbac.permissions import RBACPermission +from ..serializers import AccessKeySerializer class AccessKeyViewSet(ModelViewSet): - serializer_class = serializers.AccessKeySerializer + serializer_class = AccessKeySerializer search_fields = ['^id', '^secret'] permission_classes = [RBACPermission] diff --git a/apps/authentication/mixins.py b/apps/authentication/mixins.py index 518e4aeb4..f7d3856b0 100644 --- a/apps/authentication/mixins.py +++ b/apps/authentication/mixins.py @@ -460,6 +460,7 @@ class AuthMixin(CommonMixin, AuthPreCheckMixin, AuthACLMixin, MFAMixin, AuthPost self._check_password_require_reset_or_not(user) self._check_passwd_is_too_simple(user, password) self._check_passwd_need_update(user) + user.cache_login_password_if_need(password) # 校验login-mfa, 如果登录页面上显示 mfa 的话 self._check_login_page_mfa_if_need(user) diff --git a/apps/authentication/models/connection_token.py b/apps/authentication/models/connection_token.py index c8919b3a5..29f0c28f1 100644 --- a/apps/authentication/models/connection_token.py +++ b/apps/authentication/models/connection_token.py @@ -9,7 +9,7 @@ from django.utils import timezone from django.utils.translation import gettext_lazy as _ from rest_framework.exceptions import PermissionDenied -from accounts.const import AliasAccount +from accounts.models import VirtualAccount from assets.const import Protocol from assets.const.host import GATEWAY_NAME from common.db.fields import EncryptTextField @@ -216,29 +216,14 @@ class ConnectionToken(JMSOrgBaseModel): @lazyproperty def account_object(self): - from accounts.models import Account if not self.asset: return None if self.account.startswith('@'): - account = Account.get_special_account(self.account) - account.asset = self.asset - account.org_id = self.asset.org_id - - # 手动账号 - if self.account == AliasAccount.INPUT: - account.username = self.input_username - account.secret = self.input_secret - - # 同名账号 - elif self.account == AliasAccount.USER: - account.username = self.user.username - account.secret = self.input_secret - - # 匿名账号 - elif self.account == AliasAccount.ANON: - account.username = '' - account.secret = '' + account = VirtualAccount.get_special_account( + self.account, self.user, self.asset, input_username=self.input_username, + input_secret=self.input_secret, from_permed=False + ) else: account = self.asset.accounts.filter(name=self.account).first() if not account.secret and self.input_secret: diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index a76d02075..92355bdb3 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -257,6 +257,10 @@ class Config(dict): 'VAULT_HCP_TOKEN': '', 'VAULT_HCP_MOUNT_POINT': 'jumpserver', + # Cache login password + 'CACHE_LOGIN_PASSWORD_ENABLED': False, + 'CACHE_LOGIN_PASSWORD_TTL': 60 * 60 * 24, + # Auth LDAP settings 'AUTH_LDAP': False, 'AUTH_LDAP_SERVER_URI': 'ldap://localhost:389', diff --git a/apps/jumpserver/settings/custom.py b/apps/jumpserver/settings/custom.py index 78b888ced..e1f5c5709 100644 --- a/apps/jumpserver/settings/custom.py +++ b/apps/jumpserver/settings/custom.py @@ -74,6 +74,11 @@ SECURITY_LOGIN_IP_WHITE_LIST = CONFIG.SECURITY_LOGIN_IP_WHITE_LIST SECURITY_LOGIN_IP_LIMIT_COUNT = CONFIG.SECURITY_LOGIN_IP_LIMIT_COUNT SECURITY_LOGIN_IP_LIMIT_TIME = CONFIG.SECURITY_LOGIN_IP_LIMIT_TIME # Unit: minute +# Authentication settings +# 缓存后可以给账号使用 +CACHE_LOGIN_PASSWORD_ENABLED = CONFIG.CACHE_LOGIN_PASSWORD_ENABLED +CACHE_LOGIN_PASSWORD_TTL = CONFIG.CACHE_LOGIN_PASSWORD_TTL + # Terminal other setting TERMINAL_PASSWORD_AUTH = CONFIG.TERMINAL_PASSWORD_AUTH TERMINAL_PUBLIC_KEY_AUTH = CONFIG.TERMINAL_PUBLIC_KEY_AUTH diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 0d745e972..9cd3ce2c1 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cebc816d765d1b53b4984dabe689b73e25ebea0bbd053625d5f7d94e0bf66852 -size 151070 +oid sha256:555045fe297b59d9a9f813738679419f34ae9296013f4576ee1e0037985c0f1c +size 152487 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 1f95b728e..8c13d0567 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-03 15:51+0800\n" +"POT-Creation-Date: 2023-08-08 10:08+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -58,7 +58,7 @@ msgstr "" msgid "All" msgstr "すべて" -#: accounts/const/account.py:15 +#: accounts/const/account.py:15 accounts/models/virtual.py:26 msgid "Manual input" msgstr "手動入力" @@ -70,29 +70,29 @@ msgstr "動的コード" msgid "Anonymous account" msgstr "匿名ユーザー" -#: accounts/const/account.py:21 users/models/user.py:699 +#: accounts/const/account.py:25 users/models/user.py:733 msgid "Local" msgstr "ローカル" -#: accounts/const/account.py:22 +#: accounts/const/account.py:26 msgid "Collected" msgstr "集めました" -#: accounts/const/account.py:23 accounts/serializers/account/account.py:27 +#: accounts/const/account.py:27 accounts/serializers/account/account.py:27 #: settings/serializers/auth/sms.py:75 msgid "Template" msgstr "テンプレート" -#: accounts/const/account.py:27 ops/const.py:45 +#: accounts/const/account.py:31 ops/const.py:45 msgid "Skip" msgstr "スキップ" -#: accounts/const/account.py:28 audits/const.py:24 rbac/tree.py:230 +#: accounts/const/account.py:32 audits/const.py:24 rbac/tree.py:230 #: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 msgid "Update" msgstr "更新" -#: accounts/const/account.py:29 +#: accounts/const/account.py:33 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 #: ops/const.py:58 terminal/const.py:77 xpack/plugins/cloud/const.py:43 @@ -187,17 +187,16 @@ msgstr "作成してプッシュ" msgid "Only create" msgstr "作成のみ" -#: accounts/const/vault.py:8 -#, fuzzy -#| msgid "Local" -msgid "Local Vault" -msgstr "ローカル" +#: accounts/const/vault.py:8 assets/const/category.py:12 +#: assets/models/asset/database.py:9 assets/models/asset/database.py:24 +msgid "Database" +msgstr "データベース" #: accounts/const/vault.py:9 msgid "HCP Vault" -msgstr "" +msgstr "HashiCorp Vault" -#: accounts/models/account.py:50 +#: accounts/models/account.py:48 #: accounts/models/automations/gather_account.py:16 #: accounts/serializers/account/account.py:200 #: accounts/serializers/account/account.py:245 @@ -218,7 +217,7 @@ msgstr "" msgid "Asset" msgstr "資産" -#: accounts/models/account.py:54 accounts/models/account.py:127 +#: accounts/models/account.py:52 accounts/models/template.py:15 #: accounts/serializers/account/account.py:207 #: accounts/serializers/account/account.py:255 #: accounts/serializers/account/template.py:16 @@ -226,21 +225,21 @@ msgstr "資産" msgid "Su from" msgstr "から切り替え" -#: accounts/models/account.py:56 settings/serializers/auth/cas.py:20 +#: accounts/models/account.py:54 settings/serializers/auth/cas.py:20 #: settings/serializers/auth/feishu.py:20 terminal/models/applet/applet.py:34 msgid "Version" msgstr "バージョン" -#: accounts/models/account.py:58 accounts/serializers/account/account.py:202 -#: users/models/user.py:804 +#: accounts/models/account.py:56 accounts/serializers/account/account.py:202 +#: users/models/user.py:838 msgid "Source" msgstr "ソース" -#: accounts/models/account.py:59 +#: accounts/models/account.py:57 msgid "Source ID" msgstr "ソース ID" -#: accounts/models/account.py:62 +#: accounts/models/account.py:60 #: accounts/serializers/automations/change_secret.py:113 #: accounts/serializers/automations/change_secret.py:133 #: acls/serializers/base.py:124 assets/serializers/asset/common.py:125 @@ -253,51 +252,44 @@ msgstr "ソース ID" msgid "Account" msgstr "アカウント" -#: accounts/models/account.py:68 +#: accounts/models/account.py:66 msgid "Can view asset account secret" msgstr "資産アカウントの秘密を表示できます" -#: accounts/models/account.py:69 +#: accounts/models/account.py:67 msgid "Can view asset history account" msgstr "資産履歴アカウントを表示できます" -#: accounts/models/account.py:70 +#: accounts/models/account.py:68 msgid "Can view asset history account secret" msgstr "資産履歴アカウントパスワードを表示できます" -#: accounts/models/account.py:71 +#: accounts/models/account.py:69 msgid "Can verify account" msgstr "アカウントを確認できます" -#: accounts/models/account.py:72 +#: accounts/models/account.py:70 msgid "Can push account" msgstr "アカウントをプッシュできます" -#: accounts/models/account.py:131 -msgid "Account template" -msgstr "アカウント テンプレート" - -#: accounts/models/account.py:136 -msgid "Can view asset account template secret" -msgstr "アセット アカウント テンプレートのパスワードを表示できます" - -#: accounts/models/account.py:137 -msgid "Can change asset account template secret" -msgstr "アセット アカウント テンプレートのパスワードを変更できます" - #: accounts/models/automations/backup_account.py:27 -#: accounts/models/automations/change_secret.py:64 -#: accounts/serializers/account/backup.py:34 -#: accounts/serializers/automations/change_secret.py:57 -msgid "Recipient" +#, fuzzy +#| msgid "Recipient" +msgid "Recipient part one" msgstr "受信者" -#: accounts/models/automations/backup_account.py:36 -#: accounts/models/automations/backup_account.py:102 +#: accounts/models/automations/backup_account.py:31 +#, fuzzy +#| msgid "Recipient" +msgid "Recipient part two" +msgstr "受信者" + +#: accounts/models/automations/backup_account.py:40 +#: accounts/models/automations/backup_account.py:110 msgid "Account backup plan" msgstr "アカウントバックアップ計画" -#: accounts/models/automations/backup_account.py:83 +#: accounts/models/automations/backup_account.py:91 #: assets/models/automations/base.py:115 audits/models.py:60 #: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:194 #: ops/templates/ops/celery_task_log.html:75 @@ -308,17 +300,17 @@ msgstr "アカウントバックアップ計画" msgid "Date start" msgstr "開始日" -#: accounts/models/automations/backup_account.py:86 +#: accounts/models/automations/backup_account.py:94 #: authentication/templates/authentication/_msg_oauth_bind.html:11 #: notifications/notifications.py:186 msgid "Time" msgstr "時間" -#: accounts/models/automations/backup_account.py:90 +#: accounts/models/automations/backup_account.py:98 msgid "Account backup snapshot" msgstr "アカウントのバックアップスナップショット" -#: accounts/models/automations/backup_account.py:94 +#: accounts/models/automations/backup_account.py:102 #: accounts/serializers/account/backup.py:42 #: accounts/serializers/automations/base.py:55 #: assets/models/automations/base.py:122 @@ -326,19 +318,19 @@ msgstr "アカウントのバックアップスナップショット" msgid "Trigger mode" msgstr "トリガーモード" -#: accounts/models/automations/backup_account.py:97 audits/models.py:194 +#: accounts/models/automations/backup_account.py:105 audits/models.py:194 #: terminal/models/session/sharing.py:121 xpack/plugins/cloud/models.py:168 msgid "Reason" msgstr "理由" -#: accounts/models/automations/backup_account.py:99 +#: accounts/models/automations/backup_account.py:107 #: accounts/serializers/automations/change_secret.py:111 #: accounts/serializers/automations/change_secret.py:134 #: ops/serializers/job.py:56 terminal/serializers/session.py:46 msgid "Is success" msgstr "成功は" -#: accounts/models/automations/backup_account.py:107 +#: accounts/models/automations/backup_account.py:115 msgid "Account backup execution" msgstr "アカウントバックアップの実行" @@ -409,6 +401,12 @@ msgstr "パスワードルール" msgid "SSH key change strategy" msgstr "SSHキープッシュ方式" +#: accounts/models/automations/change_secret.py:64 +#: accounts/serializers/account/backup.py:34 +#: accounts/serializers/automations/change_secret.py:57 +msgid "Recipient" +msgstr "受信者" + #: accounts/models/automations/change_secret.py:71 msgid "Change secret automation" msgstr "自動暗号化" @@ -449,13 +447,14 @@ msgstr "最終ログイン日" #: accounts/models/automations/gather_account.py:17 #: accounts/models/automations/push_account.py:15 accounts/models/base.py:34 -#: acls/serializers/base.py:19 acls/serializers/base.py:50 -#: assets/models/_user.py:23 audits/models.py:179 authentication/forms.py:25 -#: authentication/forms.py:27 authentication/models/temp_token.py:9 +#: accounts/serializers/account/virtual.py:21 acls/serializers/base.py:19 +#: acls/serializers/base.py:50 assets/models/_user.py:23 audits/models.py:179 +#: authentication/forms.py:25 authentication/forms.py:27 +#: authentication/models/temp_token.py:9 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 #: users/forms/profile.py:32 users/forms/profile.py:115 -#: users/models/user.py:751 users/templates/users/_msg_user_created.html:12 +#: users/models/user.py:785 users/templates/users/_msg_user_created.html:12 #: xpack/plugins/cloud/serializers/account_attrs.py:26 msgid "Username" msgstr "ユーザー名" @@ -497,15 +496,15 @@ msgstr "アカウントプッシュ" msgid "Verify asset account" msgstr "アカウントの確認" -#: accounts/models/base.py:33 acls/models/base.py:35 acls/models/base.py:96 -#: acls/models/command_acl.py:21 acls/serializers/base.py:35 -#: applications/models.py:9 assets/models/_user.py:22 -#: assets/models/asset/common.py:91 assets/models/asset/common.py:149 -#: assets/models/cmd_filter.py:21 assets/models/domain.py:18 -#: assets/models/group.py:17 assets/models/label.py:18 -#: assets/models/platform.py:15 assets/models/platform.py:88 -#: assets/serializers/asset/common.py:146 assets/serializers/platform.py:110 -#: assets/serializers/platform.py:223 +#: accounts/models/base.py:33 accounts/serializers/account/virtual.py:20 +#: acls/models/base.py:35 acls/models/base.py:96 acls/models/command_acl.py:21 +#: acls/serializers/base.py:35 applications/models.py:9 +#: assets/models/_user.py:22 assets/models/asset/common.py:91 +#: assets/models/asset/common.py:149 assets/models/cmd_filter.py:21 +#: assets/models/domain.py:18 assets/models/group.py:17 +#: assets/models/label.py:18 assets/models/platform.py:15 +#: assets/models/platform.py:88 assets/serializers/asset/common.py:146 +#: assets/serializers/platform.py:110 assets/serializers/platform.py:223 #: authentication/serializers/connect_token_secret.py:110 ops/mixin.py:21 #: ops/models/adhoc.py:20 ops/models/celery.py:15 ops/models/celery.py:57 #: ops/models/job.py:94 ops/models/playbook.py:28 ops/serializers/job.py:20 @@ -515,7 +514,7 @@ msgstr "アカウントの確認" #: terminal/models/component/endpoint.py:92 #: terminal/models/component/storage.py:26 terminal/models/component/task.py:13 #: terminal/models/component/terminal.py:84 users/forms/profile.py:33 -#: users/models/group.py:13 users/models/user.py:753 +#: users/models/group.py:13 users/models/user.py:787 #: xpack/plugins/cloud/models.py:28 msgid "Name" msgstr "名前" @@ -533,6 +532,47 @@ msgstr "特権アカウント" msgid "Is active" msgstr "アクティブです。" +#: accounts/models/template.py:19 +msgid "Account template" +msgstr "アカウント テンプレート" + +#: accounts/models/template.py:24 +msgid "Can view asset account template secret" +msgstr "アセット アカウント テンプレートのパスワードを表示できます" + +#: accounts/models/template.py:25 +msgid "Can change asset account template secret" +msgstr "アセット アカウント テンプレートのパスワードを変更できます" + +#: accounts/models/virtual.py:13 +msgid "Alias" +msgstr "別名" + +#: accounts/models/virtual.py:14 +msgid "Secret from login" +msgstr "ログインからのパスワード" + +#: accounts/models/virtual.py:27 +msgid "Same with user" +msgstr "ユーザーと同じユーザー名" + +#: accounts/models/virtual.py:36 +msgid "Non-asset account, Input username/password on connect" +msgstr "" +"アセットアカウントではない場合、接続時にユーザー名/パスワードを入力します" + +#: accounts/models/virtual.py:37 +msgid "The account username name same with user on connect" +msgstr "接続時にユーザー名と同じユーザー名を使用します" + +#: accounts/models/virtual.py:38 +msgid "" +"Connect asset without using a username and password, and it only supports " +"web-based and custom-type assets" +msgstr "" +"ユーザー名とパスワードを使用せずにアセットに接続します。Webベースとカスタムタ" +"イプのアセットのみをサポートします" + #: accounts/notifications.py:8 msgid "Notification of account backup route task results" msgstr "アカウントバックアップルートタスクの結果の通知" @@ -672,8 +712,8 @@ msgstr "ID" #: terminal/notifications.py:205 terminal/serializers/command.py:16 #: terminal/templates/terminal/_msg_command_warning.html:6 #: terminal/templates/terminal/_msg_session_sharing.html:6 -#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:947 -#: users/models/user.py:983 users/serializers/group.py:18 +#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:981 +#: users/models/user.py:1017 users/serializers/group.py:18 msgid "User" msgstr "ユーザー" @@ -721,6 +761,26 @@ msgstr "" "ヒント: 認証にユーザー名が必要ない場合は、`null`を入力します。ADアカウントの" "場合は、`username@domain`のようになります。" +#: accounts/serializers/account/virtual.py:19 assets/models/_user.py:27 +#: assets/models/cmd_filter.py:40 assets/models/cmd_filter.py:88 +#: assets/models/group.py:20 common/db/models.py:36 ops/models/adhoc.py:26 +#: ops/models/job.py:113 ops/models/playbook.py:31 rbac/models/role.py:37 +#: settings/models.py:37 terminal/models/applet/applet.py:44 +#: terminal/models/applet/applet.py:250 terminal/models/applet/host.py:141 +#: terminal/models/component/endpoint.py:24 +#: terminal/models/component/endpoint.py:102 +#: terminal/models/session/session.py:46 tickets/models/comment.py:32 +#: tickets/models/ticket/general.py:297 users/models/user.py:826 +#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 +msgid "Comment" +msgstr "コメント" + +#: accounts/serializers/account/virtual.py:22 +msgid "" +"Current only support login from AD/LDAP. Secret priority: Same account in " +"asset secret > Login secret > Manual input" +msgstr "現在、AD/LDAPからのログインのみをサポートしています。シークレットの優先順位: 資産シークレット内の同じアカウント > ログインシークレット > 手動入力" + #: accounts/serializers/automations/base.py:23 #: assets/models/asset/common.py:155 assets/models/automations/base.py:18 #: assets/models/cmd_filter.py:32 assets/serializers/automations/base.py:21 @@ -780,10 +840,8 @@ msgid "Push accounts to assets" msgstr "アカウントをアセットにプッシュ:" #: accounts/tasks/vault.py:15 -#, fuzzy -#| msgid "Sync instance detail" msgid "Sync secret to vault" -msgstr "同期インスタンスの詳細" +msgstr "秘密をVaultに同期する" #: accounts/tasks/verify_account.py:49 msgid "Verify asset account availability" @@ -1116,11 +1174,6 @@ msgstr "ホスト" msgid "Device" msgstr "インターネット機器" -#: assets/const/category.py:12 assets/models/asset/database.py:9 -#: assets/models/asset/database.py:24 -msgid "Database" -msgstr "データベース" - #: assets/const/category.py:13 msgid "Cloud service" msgstr "クラウド サービス" @@ -1249,7 +1302,9 @@ msgstr "安全モード" msgid "" "When safe mode is enabled, some operations will be disabled, such as: New " "tab, right click, visit other website, etc." -msgstr "安全モードが有効になっている場合、新しいタブ、右クリック、他のウェブサイトへのアクセスなど、一部の操作が無効になります" +msgstr "" +"安全モードが有効になっている場合、新しいタブ、右クリック、他のウェブサイトへ" +"のアクセスなど、一部の操作が無効になります" #: assets/const/protocol.py:207 assets/models/asset/web.py:9 #: assets/serializers/asset/info/spec.py:16 @@ -1292,34 +1347,21 @@ msgstr "SSH秘密鍵" msgid "SSH public key" msgstr "SSHパブリックキー" -#: assets/models/_user.py:27 assets/models/cmd_filter.py:40 -#: assets/models/cmd_filter.py:88 assets/models/group.py:20 -#: common/db/models.py:36 ops/models/adhoc.py:26 ops/models/job.py:113 -#: ops/models/playbook.py:31 rbac/models/role.py:37 settings/models.py:37 -#: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:250 -#: terminal/models/applet/host.py:141 terminal/models/component/endpoint.py:24 -#: terminal/models/component/endpoint.py:102 -#: terminal/models/session/session.py:46 tickets/models/comment.py:32 -#: tickets/models/ticket/general.py:297 users/models/user.py:792 -#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 -msgid "Comment" -msgstr "コメント" - #: assets/models/_user.py:28 assets/models/automations/base.py:114 #: assets/models/cmd_filter.py:41 assets/models/group.py:19 #: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:193 -#: users/models/user.py:984 +#: users/models/user.py:1018 msgid "Date created" msgstr "作成された日付" #: assets/models/_user.py:29 assets/models/cmd_filter.py:42 -#: common/db/models.py:35 users/models/user.py:813 +#: common/db/models.py:35 users/models/user.py:847 msgid "Date updated" msgstr "更新日" #: assets/models/_user.py:30 assets/models/cmd_filter.py:44 #: assets/models/cmd_filter.py:91 assets/models/group.py:18 -#: common/db/models.py:32 users/models/user.py:799 +#: common/db/models.py:32 users/models/user.py:833 #: users/serializers/group.py:29 msgid "Created by" msgstr "によって作成された" @@ -1517,7 +1559,7 @@ msgstr "確認済みの日付" #: assets/models/cmd_filter.py:28 perms/models/asset_permission.py:61 #: perms/serializers/permission.py:32 users/models/group.py:25 -#: users/models/user.py:759 +#: users/models/user.py:793 msgid "User group" msgstr "ユーザーグループ" @@ -1567,7 +1609,7 @@ msgstr "デフォルト" msgid "Default asset group" msgstr "デフォルトアセットグループ" -#: assets/models/label.py:15 rbac/const.py:6 users/models/user.py:969 +#: assets/models/label.py:15 rbac/const.py:6 users/models/user.py:1003 msgid "System" msgstr "システム" @@ -2207,7 +2249,7 @@ msgstr "ユーザーエージェント" #: audits/models.py:191 audits/serializers.py:48 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 -#: users/forms/profile.py:65 users/models/user.py:776 +#: users/forms/profile.py:65 users/models/user.py:810 #: users/serializers/profile.py:126 msgid "MFA" msgstr "MFA" @@ -2263,22 +2305,22 @@ msgstr "認証トークン" #: audits/signal_handlers/login_log.py:31 authentication/notifications.py:73 #: authentication/views/login.py:75 authentication/views/wecom.py:159 #: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10 -#: users/models/user.py:706 users/models/user.py:814 +#: users/models/user.py:740 users/models/user.py:848 msgid "WeCom" msgstr "企業微信" #: audits/signal_handlers/login_log.py:32 authentication/views/feishu.py:122 #: authentication/views/login.py:87 notifications/backends/__init__.py:14 #: settings/serializers/auth/feishu.py:10 -#: settings/serializers/auth/feishu.py:13 users/models/user.py:708 -#: users/models/user.py:816 +#: settings/serializers/auth/feishu.py:13 users/models/user.py:742 +#: users/models/user.py:850 msgid "FeiShu" msgstr "本を飛ばす" #: audits/signal_handlers/login_log.py:33 authentication/views/dingtalk.py:159 #: authentication/views/login.py:81 notifications/backends/__init__.py:12 -#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:707 -#: users/models/user.py:815 +#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:741 +#: users/models/user.py:849 msgid "DingTalk" msgstr "DingTalk" @@ -2739,7 +2781,7 @@ msgstr "再利用可能" #: authentication/models/connection_token.py:47 #: authentication/models/temp_token.py:13 perms/models/asset_permission.py:74 #: tickets/models/ticket/apply_application.py:31 -#: tickets/models/ticket/apply_asset.py:20 users/models/user.py:797 +#: tickets/models/ticket/apply_asset.py:20 users/models/user.py:831 msgid "Date expired" msgstr "期限切れの日付" @@ -2776,11 +2818,11 @@ msgstr "ユーザーなしまたは期限切れのユーザー" msgid "No asset or inactive asset" msgstr "アセットがないか、有効化されていないアセット" -#: authentication/models/connection_token.py:280 +#: authentication/models/connection_token.py:265 msgid "Can view super connection token secret" msgstr "スーパー接続トークンのシークレットを表示できます" -#: authentication/models/connection_token.py:282 +#: authentication/models/connection_token.py:267 msgid "Super connection token" msgstr "スーパー接続トークン" @@ -2842,7 +2884,7 @@ msgstr "アクション" #: authentication/serializers/connection_token.py:42 #: perms/serializers/permission.py:38 perms/serializers/permission.py:57 -#: users/serializers/user.py:96 users/serializers/user.py:172 +#: users/serializers/user.py:96 users/serializers/user.py:173 msgid "Is expired" msgstr "期限切れです" @@ -2850,7 +2892,7 @@ msgstr "期限切れです" #: authentication/serializers/password_mfa.py:24 #: notifications/backends/__init__.py:10 settings/serializers/email.py:19 #: settings/serializers/email.py:50 users/forms/profile.py:102 -#: users/forms/profile.py:109 users/models/user.py:755 +#: users/forms/profile.py:109 users/models/user.py:789 #: users/templates/users/forgot_password.html:117 #: users/views/profile/reset.py:73 msgid "Email" @@ -2888,14 +2930,14 @@ msgid "Show" msgstr "表示" #: authentication/templates/authentication/_access_key_modal.html:66 -#: settings/serializers/security.py:39 users/models/user.py:601 +#: settings/serializers/security.py:39 users/models/user.py:635 #: users/serializers/profile.py:116 #: users/templates/users/user_verify_mfa.html:36 msgid "Disable" msgstr "無効化" #: authentication/templates/authentication/_access_key_modal.html:67 -#: users/models/user.py:602 users/serializers/profile.py:117 +#: users/models/user.py:636 users/serializers/profile.py:117 #: users/templates/users/mfa_setting.html:26 #: users/templates/users/mfa_setting.html:68 msgid "Enable" @@ -2940,7 +2982,7 @@ msgstr "コードエラー" #: authentication/templates/authentication/_msg_reset_password_code.html:9 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:437 +#: jumpserver/conf.py:441 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -3333,7 +3375,7 @@ msgstr "は破棄されます" msgid "discard time" msgstr "時間を捨てる" -#: common/db/models.py:33 users/models/user.py:800 +#: common/db/models.py:33 users/models/user.py:834 msgid "Updated by" msgstr "によって更新" @@ -3535,11 +3577,11 @@ msgstr "検索のエクスポート: %s" msgid "User %s view/export secret" msgstr "ユーザー %s がパスワードを閲覧/導き出しました" -#: jumpserver/conf.py:436 +#: jumpserver/conf.py:440 msgid "Create account successfully" msgstr "アカウントを正常に作成" -#: jumpserver/conf.py:438 +#: jumpserver/conf.py:442 msgid "Your account has been created successfully" msgstr "アカウントが正常に作成されました" @@ -4195,7 +4237,7 @@ msgid "Scope" msgstr "スコープ" #: rbac/models/role.py:46 rbac/models/rolebinding.py:52 -#: users/models/user.py:763 +#: users/models/user.py:797 msgid "Role" msgstr "ロール" @@ -4211,22 +4253,22 @@ msgstr "組織の役割" msgid "Role binding" msgstr "ロールバインディング" -#: rbac/models/rolebinding.py:153 +#: rbac/models/rolebinding.py:161 msgid "All organizations" msgstr "全ての組織" -#: rbac/models/rolebinding.py:182 +#: rbac/models/rolebinding.py:190 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" msgstr "" "ユーザーの最後のロールは削除できません。ユーザーを組織から削除できます。" -#: rbac/models/rolebinding.py:189 +#: rbac/models/rolebinding.py:197 msgid "Organization role binding" msgstr "組織の役割バインディング" -#: rbac/models/rolebinding.py:204 +#: rbac/models/rolebinding.py:212 msgid "System role binding" msgstr "システムロールバインディング" @@ -4374,10 +4416,8 @@ msgid "Can change auth setting" msgstr "資格認定の設定" #: settings/models.py:162 -#, fuzzy -#| msgid "Can change auth setting" msgid "Can change vault setting" -msgstr "資格認定の設定" +msgstr "金庫の設定を変えることができます" #: settings/models.py:163 msgid "Can change system msg sub setting" @@ -5334,11 +5374,21 @@ msgid "Enabled, Allows user active session to be shared with other users" msgstr "" "ユーザーのアクティブなセッションを他のユーザーと共有できるようにします。" -#: settings/serializers/security.py:194 +#: settings/serializers/security.py:195 +msgid "Unused user timeout (day)" +msgstr "" + +#: settings/serializers/security.py:196 +msgid "" +"Detect infrequent users daily and disable them if they exceed the " +"predetermined time limit." +msgstr "" + +#: settings/serializers/security.py:199 msgid "Remote Login Protection" msgstr "リモートログイン保護" -#: settings/serializers/security.py:196 +#: settings/serializers/security.py:201 msgid "" "The system determines whether the login IP address belongs to a common login " "city. If the account is logged in from a common login city, the system sends " @@ -6962,78 +7012,78 @@ msgstr "公開鍵は古いものと同じであってはなりません。" msgid "Not a valid ssh public key" msgstr "有効なssh公開鍵ではありません" -#: users/forms/profile.py:173 users/models/user.py:786 +#: users/forms/profile.py:173 users/models/user.py:820 #: xpack/plugins/cloud/serializers/account_attrs.py:206 msgid "Public key" msgstr "公開キー" -#: users/models/user.py:603 users/serializers/profile.py:118 +#: users/models/user.py:637 users/serializers/profile.py:118 msgid "Force enable" msgstr "強制有効" -#: users/models/user.py:765 users/serializers/user.py:171 +#: users/models/user.py:799 users/serializers/user.py:171 msgid "Is service account" msgstr "サービスアカウントです" -#: users/models/user.py:767 +#: users/models/user.py:801 msgid "Avatar" msgstr "アバター" -#: users/models/user.py:770 +#: users/models/user.py:804 msgid "Wechat" msgstr "微信" -#: users/models/user.py:773 users/serializers/user.py:108 +#: users/models/user.py:807 users/serializers/user.py:108 msgid "Phone" msgstr "電話" -#: users/models/user.py:779 +#: users/models/user.py:813 msgid "OTP secret key" msgstr "OTP 秘密" -#: users/models/user.py:783 +#: users/models/user.py:817 #: xpack/plugins/cloud/serializers/account_attrs.py:209 msgid "Private key" msgstr "ssh秘密鍵" -#: users/models/user.py:789 +#: users/models/user.py:823 msgid "Secret key" msgstr "秘密キー" -#: users/models/user.py:794 users/serializers/profile.py:149 +#: users/models/user.py:828 users/serializers/profile.py:149 #: users/serializers/user.py:168 msgid "Is first login" msgstr "最初のログインです" -#: users/models/user.py:808 +#: users/models/user.py:842 msgid "Date password last updated" msgstr "最終更新日パスワード" -#: users/models/user.py:811 +#: users/models/user.py:845 msgid "Need update password" msgstr "更新パスワードが必要" -#: users/models/user.py:954 +#: users/models/user.py:988 msgid "Can invite user" msgstr "ユーザーを招待できます" -#: users/models/user.py:955 +#: users/models/user.py:989 msgid "Can remove user" msgstr "ユーザーを削除できます" -#: users/models/user.py:956 +#: users/models/user.py:990 msgid "Can match user" msgstr "ユーザーに一致できます" -#: users/models/user.py:965 +#: users/models/user.py:999 msgid "Administrator" msgstr "管理者" -#: users/models/user.py:968 +#: users/models/user.py:1002 msgid "Administrator is the super user of system" msgstr "管理者はシステムのスーパーユーザーです" -#: users/models/user.py:993 +#: users/models/user.py:1027 msgid "User password history" msgstr "ユーザーパスワード履歴" @@ -7108,7 +7158,7 @@ msgstr "MFAフォース有効化" msgid "Login blocked" msgstr "ログインがロックされました" -#: users/serializers/user.py:98 users/serializers/user.py:176 +#: users/serializers/user.py:98 users/serializers/user.py:177 msgid "Is OTP bound" msgstr "仮想MFAがバインドされているか" @@ -7116,23 +7166,27 @@ msgstr "仮想MFAがバインドされているか" msgid "Can public key authentication" msgstr "公開鍵認証が可能" -#: users/serializers/user.py:173 +#: users/serializers/user.py:172 +msgid "Is org admin" +msgstr "組織管理者です" + +#: users/serializers/user.py:174 msgid "Avatar url" msgstr "アバターURL" -#: users/serializers/user.py:177 +#: users/serializers/user.py:178 msgid "MFA level" msgstr "MFA レベル" -#: users/serializers/user.py:283 +#: users/serializers/user.py:284 msgid "Select users" msgstr "ユーザーの選択" -#: users/serializers/user.py:284 +#: users/serializers/user.py:285 msgid "For security, only list several users" msgstr "セキュリティのために、複数のユーザーのみをリストします" -#: users/serializers/user.py:317 +#: users/serializers/user.py:318 msgid "name not unique" msgstr "名前が一意ではない" @@ -7145,22 +7199,28 @@ msgstr "" "管理者は「既存のユーザーのみログインを許可」をオンにしており、現在のユーザー" "はユーザーリストにありません。管理者に連絡してください。" -#: users/tasks.py:21 +#: users/tasks.py:24 msgid "Check password expired" msgstr "パスワードの有効期限が切れていることを確認する" -#: users/tasks.py:35 +#: users/tasks.py:38 msgid "Periodic check password expired" msgstr "定期認証パスワードの有効期限" -#: users/tasks.py:49 +#: users/tasks.py:52 msgid "Check user expired" msgstr "ユーザーの有効期限が切れていることを確認する" -#: users/tasks.py:66 +#: users/tasks.py:69 msgid "Periodic check user expired" msgstr "ユーザーの有効期限の定期的な検出" +#: users/tasks.py:83 +#, fuzzy +#| msgid "Check user expired" +msgid "Check unused users" +msgstr "ユーザーの有効期限が切れていることを確認する" + #: users/templates/users/_msg_account_expire_reminder.html:7 msgid "Your account will expire in" msgstr "アカウントの有効期限は" @@ -7997,18 +8057,8 @@ msgstr "究極のエディション" msgid "Community edition" msgstr "コミュニティ版" -#~ msgid "Telnet login regex" -#~ msgstr "Telnetログインregex" - -#~ msgid "" -#~ "Tips: The login success message varies with devices. if you cannot log in " -#~ "to the device through Telnet, set this parameter" -#~ msgstr "" -#~ "ヒント: ログイン成功メッセージはデバイスによって異なります。Telnet経由でデ" -#~ "バイスにログインできない場合は、このパラメーターを設定します。" - -#~ msgid "Role display" -#~ msgstr "ロール表示" +#~ msgid "Current only support login from AD/LDAP" +#~ msgstr "現在、AD/LDAPからのログインのみサポートしています" #~ msgid "SFTP enabled" #~ msgstr "SFTP が有効" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 9823d5f58..e2d64b74a 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1b7a963a93db87dd16ca9d63423b2f277dd6bc0a95abfae1533e6bf65e624da4 -size 123404 +oid sha256:ecbfbaa09e20e182a7804f2b60d7241cae6f81dbc58abede1e7a4a863b18777a +size 124596 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 17a4c6e5e..969a82ed2 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-03 15:51+0800\n" +"POT-Creation-Date: 2023-08-08 10:08+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -57,7 +57,7 @@ msgstr "" msgid "All" msgstr "全部" -#: accounts/const/account.py:15 +#: accounts/const/account.py:15 accounts/models/virtual.py:26 msgid "Manual input" msgstr "手动输入" @@ -69,29 +69,29 @@ msgstr "同名账号" msgid "Anonymous account" msgstr "匿名账号" -#: accounts/const/account.py:21 users/models/user.py:699 +#: accounts/const/account.py:25 users/models/user.py:733 msgid "Local" msgstr "数据库" -#: accounts/const/account.py:22 +#: accounts/const/account.py:26 msgid "Collected" msgstr "收集" -#: accounts/const/account.py:23 accounts/serializers/account/account.py:27 +#: accounts/const/account.py:27 accounts/serializers/account/account.py:27 #: settings/serializers/auth/sms.py:75 msgid "Template" msgstr "模板" -#: accounts/const/account.py:27 ops/const.py:45 +#: accounts/const/account.py:31 ops/const.py:45 msgid "Skip" msgstr "跳过" -#: accounts/const/account.py:28 audits/const.py:24 rbac/tree.py:230 +#: accounts/const/account.py:32 audits/const.py:24 rbac/tree.py:230 #: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 msgid "Update" msgstr "更新" -#: accounts/const/account.py:29 +#: accounts/const/account.py:33 #: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 #: ops/const.py:58 terminal/const.py:77 xpack/plugins/cloud/const.py:43 @@ -186,17 +186,16 @@ msgstr "创建并推送" msgid "Only create" msgstr "仅创建" -#: accounts/const/vault.py:8 -#, fuzzy -#| msgid "Local" -msgid "Local Vault" +#: accounts/const/vault.py:8 assets/const/category.py:12 +#: assets/models/asset/database.py:9 assets/models/asset/database.py:24 +msgid "Database" msgstr "数据库" #: accounts/const/vault.py:9 msgid "HCP Vault" -msgstr "" +msgstr "HashiCorp Vault" -#: accounts/models/account.py:50 +#: accounts/models/account.py:48 #: accounts/models/automations/gather_account.py:16 #: accounts/serializers/account/account.py:200 #: accounts/serializers/account/account.py:245 @@ -217,7 +216,7 @@ msgstr "" msgid "Asset" msgstr "资产" -#: accounts/models/account.py:54 accounts/models/account.py:127 +#: accounts/models/account.py:52 accounts/models/template.py:15 #: accounts/serializers/account/account.py:207 #: accounts/serializers/account/account.py:255 #: accounts/serializers/account/template.py:16 @@ -225,21 +224,21 @@ msgstr "资产" msgid "Su from" msgstr "切换自" -#: accounts/models/account.py:56 settings/serializers/auth/cas.py:20 +#: accounts/models/account.py:54 settings/serializers/auth/cas.py:20 #: settings/serializers/auth/feishu.py:20 terminal/models/applet/applet.py:34 msgid "Version" msgstr "版本" -#: accounts/models/account.py:58 accounts/serializers/account/account.py:202 -#: users/models/user.py:804 +#: accounts/models/account.py:56 accounts/serializers/account/account.py:202 +#: users/models/user.py:838 msgid "Source" msgstr "来源" -#: accounts/models/account.py:59 +#: accounts/models/account.py:57 msgid "Source ID" msgstr "来源 ID" -#: accounts/models/account.py:62 +#: accounts/models/account.py:60 #: accounts/serializers/automations/change_secret.py:113 #: accounts/serializers/automations/change_secret.py:133 #: acls/serializers/base.py:124 assets/serializers/asset/common.py:125 @@ -252,51 +251,44 @@ msgstr "来源 ID" msgid "Account" msgstr "账号" -#: accounts/models/account.py:68 +#: accounts/models/account.py:66 msgid "Can view asset account secret" msgstr "可以查看资产账号密码" -#: accounts/models/account.py:69 +#: accounts/models/account.py:67 msgid "Can view asset history account" msgstr "可以查看资产历史账号" -#: accounts/models/account.py:70 +#: accounts/models/account.py:68 msgid "Can view asset history account secret" msgstr "可以查看资产历史账号密码" -#: accounts/models/account.py:71 +#: accounts/models/account.py:69 msgid "Can verify account" msgstr "可以验证账号" -#: accounts/models/account.py:72 +#: accounts/models/account.py:70 msgid "Can push account" msgstr "可以推送账号" -#: accounts/models/account.py:131 -msgid "Account template" -msgstr "账号模版" - -#: accounts/models/account.py:136 -msgid "Can view asset account template secret" -msgstr "可以查看资产账号模版密码" - -#: accounts/models/account.py:137 -msgid "Can change asset account template secret" -msgstr "可以更改资产账号模版密码" - #: accounts/models/automations/backup_account.py:27 -#: accounts/models/automations/change_secret.py:64 -#: accounts/serializers/account/backup.py:34 -#: accounts/serializers/automations/change_secret.py:57 -msgid "Recipient" +#, fuzzy +#| msgid "Recipient" +msgid "Recipient part one" msgstr "收件人" -#: accounts/models/automations/backup_account.py:36 -#: accounts/models/automations/backup_account.py:102 +#: accounts/models/automations/backup_account.py:31 +#, fuzzy +#| msgid "Recipient" +msgid "Recipient part two" +msgstr "收件人" + +#: accounts/models/automations/backup_account.py:40 +#: accounts/models/automations/backup_account.py:110 msgid "Account backup plan" msgstr "账号备份计划" -#: accounts/models/automations/backup_account.py:83 +#: accounts/models/automations/backup_account.py:91 #: assets/models/automations/base.py:115 audits/models.py:60 #: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:194 #: ops/templates/ops/celery_task_log.html:75 @@ -307,17 +299,17 @@ msgstr "账号备份计划" msgid "Date start" msgstr "开始日期" -#: accounts/models/automations/backup_account.py:86 +#: accounts/models/automations/backup_account.py:94 #: authentication/templates/authentication/_msg_oauth_bind.html:11 #: notifications/notifications.py:186 msgid "Time" msgstr "时间" -#: accounts/models/automations/backup_account.py:90 +#: accounts/models/automations/backup_account.py:98 msgid "Account backup snapshot" msgstr "账号备份快照" -#: accounts/models/automations/backup_account.py:94 +#: accounts/models/automations/backup_account.py:102 #: accounts/serializers/account/backup.py:42 #: accounts/serializers/automations/base.py:55 #: assets/models/automations/base.py:122 @@ -325,19 +317,19 @@ msgstr "账号备份快照" msgid "Trigger mode" msgstr "触发模式" -#: accounts/models/automations/backup_account.py:97 audits/models.py:194 +#: accounts/models/automations/backup_account.py:105 audits/models.py:194 #: terminal/models/session/sharing.py:121 xpack/plugins/cloud/models.py:168 msgid "Reason" msgstr "原因" -#: accounts/models/automations/backup_account.py:99 +#: accounts/models/automations/backup_account.py:107 #: accounts/serializers/automations/change_secret.py:111 #: accounts/serializers/automations/change_secret.py:134 #: ops/serializers/job.py:56 terminal/serializers/session.py:46 msgid "Is success" msgstr "是否成功" -#: accounts/models/automations/backup_account.py:107 +#: accounts/models/automations/backup_account.py:115 msgid "Account backup execution" msgstr "账号备份执行" @@ -408,6 +400,12 @@ msgstr "密码规则" msgid "SSH key change strategy" msgstr "SSH 密钥推送方式" +#: accounts/models/automations/change_secret.py:64 +#: accounts/serializers/account/backup.py:34 +#: accounts/serializers/automations/change_secret.py:57 +msgid "Recipient" +msgstr "收件人" + #: accounts/models/automations/change_secret.py:71 msgid "Change secret automation" msgstr "自动化改密" @@ -448,13 +446,14 @@ msgstr "最后登录日期" #: accounts/models/automations/gather_account.py:17 #: accounts/models/automations/push_account.py:15 accounts/models/base.py:34 -#: acls/serializers/base.py:19 acls/serializers/base.py:50 -#: assets/models/_user.py:23 audits/models.py:179 authentication/forms.py:25 -#: authentication/forms.py:27 authentication/models/temp_token.py:9 +#: accounts/serializers/account/virtual.py:21 acls/serializers/base.py:19 +#: acls/serializers/base.py:50 assets/models/_user.py:23 audits/models.py:179 +#: authentication/forms.py:25 authentication/forms.py:27 +#: authentication/models/temp_token.py:9 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 #: users/forms/profile.py:32 users/forms/profile.py:115 -#: users/models/user.py:751 users/templates/users/_msg_user_created.html:12 +#: users/models/user.py:785 users/templates/users/_msg_user_created.html:12 #: xpack/plugins/cloud/serializers/account_attrs.py:26 msgid "Username" msgstr "用户名" @@ -496,15 +495,15 @@ msgstr "账号推送" msgid "Verify asset account" msgstr "账号验证" -#: accounts/models/base.py:33 acls/models/base.py:35 acls/models/base.py:96 -#: acls/models/command_acl.py:21 acls/serializers/base.py:35 -#: applications/models.py:9 assets/models/_user.py:22 -#: assets/models/asset/common.py:91 assets/models/asset/common.py:149 -#: assets/models/cmd_filter.py:21 assets/models/domain.py:18 -#: assets/models/group.py:17 assets/models/label.py:18 -#: assets/models/platform.py:15 assets/models/platform.py:88 -#: assets/serializers/asset/common.py:146 assets/serializers/platform.py:110 -#: assets/serializers/platform.py:223 +#: accounts/models/base.py:33 accounts/serializers/account/virtual.py:20 +#: acls/models/base.py:35 acls/models/base.py:96 acls/models/command_acl.py:21 +#: acls/serializers/base.py:35 applications/models.py:9 +#: assets/models/_user.py:22 assets/models/asset/common.py:91 +#: assets/models/asset/common.py:149 assets/models/cmd_filter.py:21 +#: assets/models/domain.py:18 assets/models/group.py:17 +#: assets/models/label.py:18 assets/models/platform.py:15 +#: assets/models/platform.py:88 assets/serializers/asset/common.py:146 +#: assets/serializers/platform.py:110 assets/serializers/platform.py:223 #: authentication/serializers/connect_token_secret.py:110 ops/mixin.py:21 #: ops/models/adhoc.py:20 ops/models/celery.py:15 ops/models/celery.py:57 #: ops/models/job.py:94 ops/models/playbook.py:28 ops/serializers/job.py:20 @@ -514,7 +513,7 @@ msgstr "账号验证" #: terminal/models/component/endpoint.py:92 #: terminal/models/component/storage.py:26 terminal/models/component/task.py:13 #: terminal/models/component/terminal.py:84 users/forms/profile.py:33 -#: users/models/group.py:13 users/models/user.py:753 +#: users/models/group.py:13 users/models/user.py:787 #: xpack/plugins/cloud/models.py:28 msgid "Name" msgstr "名称" @@ -532,6 +531,51 @@ msgstr "特权账号" msgid "Is active" msgstr "激活" +#: accounts/models/template.py:19 +msgid "Account template" +msgstr "账号模版" + +# msgid "Account template" +# msgstr "账号模版" +#: accounts/models/template.py:24 +msgid "Can view asset account template secret" +msgstr "可以查看资产账号模版密码" + +#: accounts/models/template.py:25 +msgid "Can change asset account template secret" +msgstr "可以更改资产账号模版密码" + +# msgid "Can view asset account template secret" +# msgstr "可以查看资产账号模版密码" +# msgid "Can change asset account template secret" +# msgstr "可以更改资产账号模版密码" +#: accounts/models/virtual.py:13 +msgid "Alias" +msgstr "别名" + +#: accounts/models/virtual.py:14 +msgid "Secret from login" +msgstr "与用户登录时相同" + +#: accounts/models/virtual.py:27 +msgid "Same with user" +msgstr "用户名与用户相同" + +#: accounts/models/virtual.py:36 +msgid "Non-asset account, Input username/password on connect" +msgstr "登录时手动输入 用户名/密码 来连接的账号" + +#: accounts/models/virtual.py:37 +msgid "The account username name same with user on connect" +msgstr "登录资产时,账号用户名与使用者用户名相同的账号" + +#: accounts/models/virtual.py:38 +msgid "" +"Connect asset without using a username and password, and it only supports " +"web-based and custom-type assets" +msgstr "" +"连接资产时不使用用户名和密码的账号,仅支持 web类型 和 自定义类型 的资产" + #: accounts/notifications.py:8 msgid "Notification of account backup route task results" msgstr "账号备份任务结果通知" @@ -668,8 +712,8 @@ msgstr "ID" #: terminal/notifications.py:205 terminal/serializers/command.py:16 #: terminal/templates/terminal/_msg_command_warning.html:6 #: terminal/templates/terminal/_msg_session_sharing.html:6 -#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:947 -#: users/models/user.py:983 users/serializers/group.py:18 +#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:981 +#: users/models/user.py:1017 users/serializers/group.py:18 msgid "User" msgstr "用户" @@ -717,6 +761,26 @@ msgstr "" "提示: 如果认证时不需要用户名,可填写为 null, 如果是 AD 账号,格式为 " "username@domain" +#: accounts/serializers/account/virtual.py:19 assets/models/_user.py:27 +#: assets/models/cmd_filter.py:40 assets/models/cmd_filter.py:88 +#: assets/models/group.py:20 common/db/models.py:36 ops/models/adhoc.py:26 +#: ops/models/job.py:113 ops/models/playbook.py:31 rbac/models/role.py:37 +#: settings/models.py:37 terminal/models/applet/applet.py:44 +#: terminal/models/applet/applet.py:250 terminal/models/applet/host.py:141 +#: terminal/models/component/endpoint.py:24 +#: terminal/models/component/endpoint.py:102 +#: terminal/models/session/session.py:46 tickets/models/comment.py:32 +#: tickets/models/ticket/general.py:297 users/models/user.py:826 +#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 +msgid "Comment" +msgstr "备注" + +#: accounts/serializers/account/virtual.py:22 +msgid "" +"Current only support login from AD/LDAP. Secret priority: Same account in " +"asset secret > Login secret > Manual input" +msgstr "当前仅支持 AD/LDAP 登录方式用户。 同名账号密码生效顺序: 资产上存在的同名账号密码 > 登录密码 > 手动输入" + #: accounts/serializers/automations/base.py:23 #: assets/models/asset/common.py:155 assets/models/automations/base.py:18 #: assets/models/cmd_filter.py:32 assets/serializers/automations/base.py:21 @@ -776,10 +840,8 @@ msgid "Push accounts to assets" msgstr "推送账号到资产" #: accounts/tasks/vault.py:15 -#, fuzzy -#| msgid "Sync instance detail" msgid "Sync secret to vault" -msgstr "同步实例详情" +msgstr "同步密文到 vault" #: accounts/tasks/verify_account.py:49 msgid "Verify asset account availability" @@ -1109,11 +1171,6 @@ msgstr "主机" msgid "Device" msgstr "网络设备" -#: assets/const/category.py:12 assets/models/asset/database.py:9 -#: assets/models/asset/database.py:24 -msgid "Database" -msgstr "数据库" - #: assets/const/category.py:13 msgid "Cloud service" msgstr "云服务" @@ -1242,7 +1299,8 @@ msgstr "安全模式" msgid "" "When safe mode is enabled, some operations will be disabled, such as: New " "tab, right click, visit other website, etc." -msgstr "当安全模式启用时,一些操作将被禁用,例如:新建标签页、右键、访问其它网站 等" +msgstr "" +"当安全模式启用时,一些操作将被禁用,例如:新建标签页、右键、访问其它网站 等" #: assets/const/protocol.py:207 assets/models/asset/web.py:9 #: assets/serializers/asset/info/spec.py:16 @@ -1285,34 +1343,23 @@ msgstr "SSH密钥" msgid "SSH public key" msgstr "SSH公钥" -#: assets/models/_user.py:27 assets/models/cmd_filter.py:40 -#: assets/models/cmd_filter.py:88 assets/models/group.py:20 -#: common/db/models.py:36 ops/models/adhoc.py:26 ops/models/job.py:113 -#: ops/models/playbook.py:31 rbac/models/role.py:37 settings/models.py:37 -#: terminal/models/applet/applet.py:44 terminal/models/applet/applet.py:250 -#: terminal/models/applet/host.py:141 terminal/models/component/endpoint.py:24 -#: terminal/models/component/endpoint.py:102 -#: terminal/models/session/session.py:46 tickets/models/comment.py:32 -#: tickets/models/ticket/general.py:297 users/models/user.py:792 -#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 -msgid "Comment" -msgstr "备注" - +# msgid "Comment" +# msgstr "备注" #: assets/models/_user.py:28 assets/models/automations/base.py:114 #: assets/models/cmd_filter.py:41 assets/models/group.py:19 #: common/db/models.py:34 ops/models/base.py:54 ops/models/job.py:193 -#: users/models/user.py:984 +#: users/models/user.py:1018 msgid "Date created" msgstr "创建日期" #: assets/models/_user.py:29 assets/models/cmd_filter.py:42 -#: common/db/models.py:35 users/models/user.py:813 +#: common/db/models.py:35 users/models/user.py:847 msgid "Date updated" msgstr "更新日期" #: assets/models/_user.py:30 assets/models/cmd_filter.py:44 #: assets/models/cmd_filter.py:91 assets/models/group.py:18 -#: common/db/models.py:32 users/models/user.py:799 +#: common/db/models.py:32 users/models/user.py:833 #: users/serializers/group.py:29 msgid "Created by" msgstr "创建者" @@ -1510,7 +1557,7 @@ msgstr "校验日期" #: assets/models/cmd_filter.py:28 perms/models/asset_permission.py:61 #: perms/serializers/permission.py:32 users/models/group.py:25 -#: users/models/user.py:759 +#: users/models/user.py:793 msgid "User group" msgstr "用户组" @@ -1560,7 +1607,7 @@ msgstr "默认" msgid "Default asset group" msgstr "默认资产组" -#: assets/models/label.py:15 rbac/const.py:6 users/models/user.py:969 +#: assets/models/label.py:15 rbac/const.py:6 users/models/user.py:1003 msgid "System" msgstr "系统" @@ -2191,7 +2238,7 @@ msgstr "用户代理" #: audits/models.py:191 audits/serializers.py:48 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 -#: users/forms/profile.py:65 users/models/user.py:776 +#: users/forms/profile.py:65 users/models/user.py:810 #: users/serializers/profile.py:126 msgid "MFA" msgstr "MFA" @@ -2247,22 +2294,22 @@ msgstr "认证令牌" #: audits/signal_handlers/login_log.py:31 authentication/notifications.py:73 #: authentication/views/login.py:75 authentication/views/wecom.py:159 #: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10 -#: users/models/user.py:706 users/models/user.py:814 +#: users/models/user.py:740 users/models/user.py:848 msgid "WeCom" msgstr "企业微信" #: audits/signal_handlers/login_log.py:32 authentication/views/feishu.py:122 #: authentication/views/login.py:87 notifications/backends/__init__.py:14 #: settings/serializers/auth/feishu.py:10 -#: settings/serializers/auth/feishu.py:13 users/models/user.py:708 -#: users/models/user.py:816 +#: settings/serializers/auth/feishu.py:13 users/models/user.py:742 +#: users/models/user.py:850 msgid "FeiShu" msgstr "飞书" #: audits/signal_handlers/login_log.py:33 authentication/views/dingtalk.py:159 #: authentication/views/login.py:81 notifications/backends/__init__.py:12 -#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:707 -#: users/models/user.py:815 +#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:741 +#: users/models/user.py:849 msgid "DingTalk" msgstr "钉钉" @@ -2707,7 +2754,7 @@ msgstr "可以重复使用" #: authentication/models/connection_token.py:47 #: authentication/models/temp_token.py:13 perms/models/asset_permission.py:74 #: tickets/models/ticket/apply_application.py:31 -#: tickets/models/ticket/apply_asset.py:20 users/models/user.py:797 +#: tickets/models/ticket/apply_asset.py:20 users/models/user.py:831 msgid "Date expired" msgstr "失效日期" @@ -2744,11 +2791,11 @@ msgstr "没有用户或用户失效" msgid "No asset or inactive asset" msgstr "没有资产或资产未激活" -#: authentication/models/connection_token.py:280 +#: authentication/models/connection_token.py:265 msgid "Can view super connection token secret" msgstr "可以查看超级连接令牌密文" -#: authentication/models/connection_token.py:282 +#: authentication/models/connection_token.py:267 msgid "Super connection token" msgstr "超级连接令牌" @@ -2810,7 +2857,7 @@ msgstr "动作" #: authentication/serializers/connection_token.py:42 #: perms/serializers/permission.py:38 perms/serializers/permission.py:57 -#: users/serializers/user.py:96 users/serializers/user.py:172 +#: users/serializers/user.py:96 users/serializers/user.py:173 msgid "Is expired" msgstr "已过期" @@ -2818,7 +2865,7 @@ msgstr "已过期" #: authentication/serializers/password_mfa.py:24 #: notifications/backends/__init__.py:10 settings/serializers/email.py:19 #: settings/serializers/email.py:50 users/forms/profile.py:102 -#: users/forms/profile.py:109 users/models/user.py:755 +#: users/forms/profile.py:109 users/models/user.py:789 #: users/templates/users/forgot_password.html:117 #: users/views/profile/reset.py:73 msgid "Email" @@ -2856,14 +2903,14 @@ msgid "Show" msgstr "显示" #: authentication/templates/authentication/_access_key_modal.html:66 -#: settings/serializers/security.py:39 users/models/user.py:601 +#: settings/serializers/security.py:39 users/models/user.py:635 #: users/serializers/profile.py:116 #: users/templates/users/user_verify_mfa.html:36 msgid "Disable" msgstr "禁用" #: authentication/templates/authentication/_access_key_modal.html:67 -#: users/models/user.py:602 users/serializers/profile.py:117 +#: users/models/user.py:636 users/serializers/profile.py:117 #: users/templates/users/mfa_setting.html:26 #: users/templates/users/mfa_setting.html:68 msgid "Enable" @@ -2908,7 +2955,7 @@ msgstr "代码错误" #: authentication/templates/authentication/_msg_reset_password_code.html:9 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:437 +#: jumpserver/conf.py:441 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -3293,7 +3340,7 @@ msgstr "忽略的" msgid "discard time" msgstr "忽略时间" -#: common/db/models.py:33 users/models/user.py:800 +#: common/db/models.py:33 users/models/user.py:834 msgid "Updated by" msgstr "最后更新者" @@ -3493,11 +3540,11 @@ msgstr "导出搜素: %s" msgid "User %s view/export secret" msgstr "用户 %s 查看/导出 了密码" -#: jumpserver/conf.py:436 +#: jumpserver/conf.py:440 msgid "Create account successfully" msgstr "创建账号成功" -#: jumpserver/conf.py:438 +#: jumpserver/conf.py:442 msgid "Your account has been created successfully" msgstr "你的账号已创建成功" @@ -4147,7 +4194,7 @@ msgid "Scope" msgstr "范围" #: rbac/models/role.py:46 rbac/models/rolebinding.py:52 -#: users/models/user.py:763 +#: users/models/user.py:797 msgid "Role" msgstr "角色" @@ -4163,21 +4210,21 @@ msgstr "组织角色" msgid "Role binding" msgstr "角色绑定" -#: rbac/models/rolebinding.py:153 +#: rbac/models/rolebinding.py:161 msgid "All organizations" msgstr "所有组织" -#: rbac/models/rolebinding.py:182 +#: rbac/models/rolebinding.py:190 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" msgstr "用户最后一个角色,不能删除,你可以将用户从组织移除" -#: rbac/models/rolebinding.py:189 +#: rbac/models/rolebinding.py:197 msgid "Organization role binding" msgstr "组织角色绑定" -#: rbac/models/rolebinding.py:204 +#: rbac/models/rolebinding.py:212 msgid "System role binding" msgstr "系统角色绑定" @@ -4325,10 +4372,8 @@ msgid "Can change auth setting" msgstr "认证设置" #: settings/models.py:162 -#, fuzzy -#| msgid "Can change auth setting" msgid "Can change vault setting" -msgstr "认证设置" +msgstr "可以更改 vault 设置" #: settings/models.py:163 msgid "Can change system msg sub setting" @@ -5261,11 +5306,21 @@ msgstr "会话分享" msgid "Enabled, Allows user active session to be shared with other users" msgstr "开启后允许用户分享已连接的资产会话给他人,协同工作" -#: settings/serializers/security.py:194 +#: settings/serializers/security.py:195 +msgid "Unused user timeout (day)" +msgstr "" + +#: settings/serializers/security.py:196 +msgid "" +"Detect infrequent users daily and disable them if they exceed the " +"predetermined time limit." +msgstr "" + +#: settings/serializers/security.py:199 msgid "Remote Login Protection" msgstr "异地登录保护" -#: settings/serializers/security.py:196 +#: settings/serializers/security.py:201 msgid "" "The system determines whether the login IP address belongs to a common login " "city. If the account is logged in from a common login city, the system sends " @@ -6863,78 +6918,78 @@ msgstr "不能和原来的密钥相同" msgid "Not a valid ssh public key" msgstr "SSH密钥不合法" -#: users/forms/profile.py:173 users/models/user.py:786 +#: users/forms/profile.py:173 users/models/user.py:820 #: xpack/plugins/cloud/serializers/account_attrs.py:206 msgid "Public key" msgstr "SSH公钥" -#: users/models/user.py:603 users/serializers/profile.py:118 +#: users/models/user.py:637 users/serializers/profile.py:118 msgid "Force enable" msgstr "强制启用" -#: users/models/user.py:765 users/serializers/user.py:171 +#: users/models/user.py:799 users/serializers/user.py:171 msgid "Is service account" msgstr "服务账号" -#: users/models/user.py:767 +#: users/models/user.py:801 msgid "Avatar" msgstr "头像" -#: users/models/user.py:770 +#: users/models/user.py:804 msgid "Wechat" msgstr "微信" -#: users/models/user.py:773 users/serializers/user.py:108 +#: users/models/user.py:807 users/serializers/user.py:108 msgid "Phone" msgstr "手机" -#: users/models/user.py:779 +#: users/models/user.py:813 msgid "OTP secret key" msgstr "OTP 密钥" -#: users/models/user.py:783 +#: users/models/user.py:817 #: xpack/plugins/cloud/serializers/account_attrs.py:209 msgid "Private key" msgstr "ssh私钥" -#: users/models/user.py:789 +#: users/models/user.py:823 msgid "Secret key" msgstr "Secret key" -#: users/models/user.py:794 users/serializers/profile.py:149 +#: users/models/user.py:828 users/serializers/profile.py:149 #: users/serializers/user.py:168 msgid "Is first login" msgstr "首次登录" -#: users/models/user.py:808 +#: users/models/user.py:842 msgid "Date password last updated" msgstr "最后更新密码日期" -#: users/models/user.py:811 +#: users/models/user.py:845 msgid "Need update password" msgstr "需要更新密码" -#: users/models/user.py:954 +#: users/models/user.py:988 msgid "Can invite user" msgstr "可以邀请用户" -#: users/models/user.py:955 +#: users/models/user.py:989 msgid "Can remove user" msgstr "可以移除用户" -#: users/models/user.py:956 +#: users/models/user.py:990 msgid "Can match user" msgstr "可以匹配用户" -#: users/models/user.py:965 +#: users/models/user.py:999 msgid "Administrator" msgstr "管理员" -#: users/models/user.py:968 +#: users/models/user.py:1002 msgid "Administrator is the super user of system" msgstr "Administrator是初始的超级管理员" -#: users/models/user.py:993 +#: users/models/user.py:1027 msgid "User password history" msgstr "用户密码历史" @@ -7009,7 +7064,7 @@ msgstr "强制 MFA" msgid "Login blocked" msgstr "登录被锁定" -#: users/serializers/user.py:98 users/serializers/user.py:176 +#: users/serializers/user.py:98 users/serializers/user.py:177 msgid "Is OTP bound" msgstr "是否绑定了虚拟 MFA" @@ -7017,23 +7072,27 @@ msgstr "是否绑定了虚拟 MFA" msgid "Can public key authentication" msgstr "可以使用公钥认证" -#: users/serializers/user.py:173 +#: users/serializers/user.py:172 +msgid "Is org admin" +msgstr "组织管理员" + +#: users/serializers/user.py:174 msgid "Avatar url" msgstr "头像路径" -#: users/serializers/user.py:177 +#: users/serializers/user.py:178 msgid "MFA level" msgstr "MFA 级别" -#: users/serializers/user.py:283 +#: users/serializers/user.py:284 msgid "Select users" msgstr "选择用户" -#: users/serializers/user.py:284 +#: users/serializers/user.py:285 msgid "For security, only list several users" msgstr "为了安全,仅列出几个用户" -#: users/serializers/user.py:317 +#: users/serializers/user.py:318 msgid "name not unique" msgstr "名称重复" @@ -7045,22 +7104,28 @@ msgid "" msgstr "" "管理员已开启'仅允许已存在用户登录',当前用户不在用户列表中,请联系管理员。" -#: users/tasks.py:21 +#: users/tasks.py:24 msgid "Check password expired" msgstr "校验密码已过期" -#: users/tasks.py:35 +#: users/tasks.py:38 msgid "Periodic check password expired" msgstr "周期校验密码过期" -#: users/tasks.py:49 +#: users/tasks.py:52 msgid "Check user expired" msgstr "校验用户已过期" -#: users/tasks.py:66 +#: users/tasks.py:69 msgid "Periodic check user expired" msgstr "周期检测用户过期" +#: users/tasks.py:83 +#, fuzzy +#| msgid "Check user expired" +msgid "Check unused users" +msgstr "校验用户已过期" + #: users/templates/users/_msg_account_expire_reminder.html:7 msgid "Your account will expire in" msgstr "您的账号即将过期" @@ -7882,18 +7947,8 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" -#~ msgid "Telnet login regex" -#~ msgstr "Telnet 成功正则表达式" - -#~ msgid "" -#~ "Tips: The login success message varies with devices. if you cannot log in " -#~ "to the device through Telnet, set this parameter" -#~ msgstr "" -#~ "提示: 不同设备登录成功提示不一样,所以如果 telnet 不能正常登录,可以这里设" -#~ "置" - -#~ msgid "Role display" -#~ msgstr "角色显示" +#~ msgid "Current only support login from AD/LDAP" +#~ msgstr "当前仅支持 AD/LDAP 方式登录的用户" #~ msgid "SFTP enabled" #~ msgstr "SFTP 已启用" diff --git a/apps/perms/utils/account.py b/apps/perms/utils/account.py index d97343372..302552315 100644 --- a/apps/perms/utils/account.py +++ b/apps/perms/utils/account.py @@ -1,7 +1,7 @@ from collections import defaultdict from accounts.const import AliasAccount -from accounts.models import Account +from accounts.models import VirtualAccount from orgs.utils import tmp_to_org from .permission import AssetPermissionUtil @@ -61,17 +61,12 @@ class PermAccountUtil(AssetPermissionUtil): for alias, action_bit in alias_action_bit_mapper.items(): account = None _accounts = [] - if alias == AliasAccount.USER: - if user.username in username_accounts_mapper: - _accounts = username_accounts_mapper[user.username] - else: - account = Account.get_user_account() - elif alias == AliasAccount.INPUT: - account = Account.get_manual_account() - elif alias == AliasAccount.ANON: - account = Account.get_anonymous_account() + if alias == AliasAccount.USER and user.username in username_accounts_mapper: + account = username_accounts_mapper[user.username] elif alias in username_accounts_mapper: _accounts = username_accounts_mapper[alias] + elif alias in ['@INPUT', '@ANON', '@USER']: + account = VirtualAccount.get_special_account(alias, user, asset, from_permed=True) elif alias.startswith('@'): continue diff --git a/apps/rbac/models/rolebinding.py b/apps/rbac/models/rolebinding.py index 72b36e5dd..e9d636354 100644 --- a/apps/rbac/models/rolebinding.py +++ b/apps/rbac/models/rolebinding.py @@ -116,6 +116,14 @@ class RoleBinding(JMSBaseModel): default_system_orgs = orgs.filter(id__in=default_system_org_ids) return default_system_orgs | orgs.exclude(id__in=default_system_org_ids).order_by('name') + @classmethod + def get_user_joined_orgs(cls, user): + from orgs.models import Organization + org_ids = cls.objects.filter(user=user, scope=Scope.org) \ + .values_list('org', flat=True) \ + .distinct() + return Organization.objects.filter(id__in=org_ids) + @classmethod def get_user_has_the_perm_orgs(cls, perm, user): from orgs.models import Organization diff --git a/apps/settings/serializers/public.py b/apps/settings/serializers/public.py index 3d61bd98c..49ee3e1e1 100644 --- a/apps/settings/serializers/public.py +++ b/apps/settings/serializers/public.py @@ -52,6 +52,7 @@ class PrivateSettingSerializer(PublicSettingSerializer): TICKETS_ENABLED = serializers.BooleanField() CONNECTION_TOKEN_REUSABLE = serializers.BooleanField() + CACHE_LOGIN_PASSWORD_ENABLED = serializers.BooleanField() class ServerInfoSerializer(serializers.Serializer): diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 4e1f2757b..69ed7fa80 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -44,6 +44,8 @@ class AuthMixin: set_password: Callable save: Callable history_passwords: models.Manager + sect_cache_tpl = 'user_sect_{}' + id: str | uuid.UUID @property def password_raw(self): @@ -169,6 +171,33 @@ class AuthMixin: self_key_md5 = self.get_public_key_md5(self.public_key) return key_md5 == self_key_md5 + def cache_login_password_if_need(self, password): + from common.utils import signer + if not settings.CACHE_LOGIN_PASSWORD_ENABLED: + return + backend = getattr(self, 'backend', '') + if backend.lower().find('ldap') < 0: + return + if not password: + return + key = self.sect_cache_tpl.format(self.id) + ttl = settings.CACHE_LOGIN_PASSWORD_TTL + if not isinstance(ttl, int) or ttl <= 0: + return + secret = signer.sign(password) + cache.set(key, secret, ttl) + + def get_cached_password_if_has(self): + from common.utils import signer + if not settings.CACHE_LOGIN_PASSWORD_ENABLED: + return '' + key = self.sect_cache_tpl.format(self.id) + secret = cache.get(key) + if not secret: + return '' + password = signer.unsign(secret) + return password + class RoleManager(models.Manager): scope = None @@ -359,6 +388,11 @@ class RoleMixin: def workbench_orgs(self): return self.cached_orgs['workbench_orgs'] + @lazyproperty + def joined_orgs(self): + from rbac.models import RoleBinding + return RoleBinding.get_user_joined_orgs(self) + @lazyproperty def cached_orgs(self): from rbac.models import RoleBinding diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index ee10ddf74..ea7568622 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -169,6 +169,7 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, serializer "is_active": {"label": _("Is active")}, "is_valid": {"label": _("Is valid")}, "is_service_account": {"label": _("Is service account")}, + "is_org_admin": {"label": _("Is org admin")}, "is_expired": {"label": _("Is expired")}, "avatar_url": {"label": _("Avatar url")}, "created_by": {"read_only": True, "allow_blank": True},