diff --git a/apps/accounts/migrations/0001_initial.py b/apps/accounts/migrations/0001_initial.py index 97ae584c4..fcae87e48 100644 --- a/apps/accounts/migrations/0001_initial.py +++ b/apps/accounts/migrations/0001_initial.py @@ -1,22 +1,17 @@ -# Generated by Django 3.2.14 on 2022-12-28 07:29 - -import uuid - -import django.db.models.deletion -import simple_history.models -from django.conf import settings -from django.db import migrations, models +# Generated by Django 4.1.13 on 2024-05-09 03:16 import common.db.encoder import common.db.fields +from django.db import migrations, models +import simple_history.models +import uuid class Migration(migrations.Migration): + initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0098_auto_20220430_2126'), ] operations = [ @@ -29,63 +24,65 @@ class Migration(migrations.Migration): ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('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')), - ('connectivity', - models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', - max_length=16, verbose_name='Connectivity')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('connectivity', models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity')), ('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')), + ('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), ('name', models.CharField(max_length=128, verbose_name='Name')), ('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')), - ('secret_type', models.CharField( - choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, - verbose_name='Secret type')), - ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')), ('privileged', models.BooleanField(default=False, verbose_name='Privileged')), ('is_active', models.BooleanField(default=True, verbose_name='Is active')), ('version', models.IntegerField(default=0, verbose_name='Version')), ('source', models.CharField(default='local', max_length=30, verbose_name='Source')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accounts', - to='assets.asset', verbose_name='Asset')), - ('su_from', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', - to='accounts.account', verbose_name='Su from')), + ('source_id', models.CharField(blank=True, max_length=128, null=True, verbose_name='Source ID')), ], options={ 'verbose_name': 'Account', - 'permissions': [('view_accountsecret', 'Can view asset account secret'), - ('view_historyaccount', 'Can view asset history account'), - ('view_historyaccountsecret', 'Can view asset history account secret')], - 'unique_together': {('username', 'asset', 'secret_type'), ('name', 'asset')}, + 'permissions': [('view_accountsecret', 'Can view asset account secret'), ('view_historyaccount', 'Can view asset history account'), ('view_historyaccountsecret', 'Can view asset history account secret'), ('verify_account', 'Can verify account'), ('push_account', 'Can push account'), ('remove_account', 'Can remove account')], }, ), migrations.CreateModel( - name='HistoricalAccount', + name='AccountBackupAutomation', fields=[ - ('id', models.UUIDField(db_index=True, default=uuid.uuid4)), - ('secret_type', models.CharField( - choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, - verbose_name='Secret type')), - ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), - ('version', models.IntegerField(default=0, verbose_name='Version')), - ('history_id', models.AutoField(primary_key=True, serialize=False)), - ('history_date', models.DateTimeField(db_index=True)), - ('history_change_reason', models.CharField(max_length=100, null=True)), - ('history_type', - models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), - ('history_user', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', - to=settings.AUTH_USER_MODEL)), + ('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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('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')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')), + ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')), + ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')), + ('types', models.JSONField(default=list)), + ('backup_type', models.CharField(choices=[('email', 'Email'), ('object_storage', 'SFTP')], default='email', max_length=128, verbose_name='Backup type')), + ('is_password_divided_by_email', models.BooleanField(default=True, verbose_name='Password divided')), + ('is_password_divided_by_obj_storage', models.BooleanField(default=True, verbose_name='Password divided')), + ('zip_encrypt_password', common.db.fields.EncryptCharField(blank=True, max_length=4096, null=True, verbose_name='Zip encrypt password')), ], options={ - 'verbose_name': 'historical Account', - 'verbose_name_plural': 'historical Accounts', - 'ordering': ('-history_date', '-history_id'), - 'get_latest_by': ('history_date', 'history_id'), + 'verbose_name': 'Account backup plan', + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='AccountBackupExecution', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('date_start', models.DateTimeField(auto_now_add=True, verbose_name='Date start')), + ('timedelta', models.FloatField(default=0.0, null=True, verbose_name='Time')), + ('snapshot', models.JSONField(blank=True, default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True, verbose_name='Account backup snapshot')), + ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')), + ('reason', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Reason')), + ('is_success', models.BooleanField(default=False, verbose_name='Is success')), + ], + options={ + 'verbose_name': 'Account backup execution', + 'ordering': ('-date_start',), }, - bases=(simple_history.models.HistoricalChanges, models.Model), ), migrations.CreateModel( name='AccountTemplate', @@ -96,23 +93,95 @@ class Migration(migrations.Migration): ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('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')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_strategy', models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy')), + ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), ('name', models.CharField(max_length=128, verbose_name='Name')), ('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')), - ('secret_type', models.CharField( - choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, - verbose_name='Secret type')), - ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')), ('privileged', models.BooleanField(default=False, verbose_name='Privileged')), ('is_active', models.BooleanField(default=True, verbose_name='Is active')), + ('auto_push', models.BooleanField(default=False, verbose_name='Auto push')), + ('push_params', models.JSONField(default=dict, verbose_name='Push params')), ], options={ 'verbose_name': 'Account template', - 'permissions': [('view_accounttemplatesecret', 'Can view asset account template secret'), - ('change_accounttemplatesecret', 'Can change asset account template secret')], - 'unique_together': {('name', 'org_id')}, + 'permissions': [('view_accounttemplatesecret', 'Can view asset account template secret'), ('change_accounttemplatesecret', 'Can change asset account template secret')], }, ), + migrations.CreateModel( + name='ChangeSecretRecord', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('old_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Old secret')), + ('new_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='New secret')), + ('date_started', models.DateTimeField(blank=True, null=True, verbose_name='Date started')), + ('date_finished', models.DateTimeField(blank=True, null=True, verbose_name='Date finished')), + ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), + ('error', models.TextField(blank=True, null=True, verbose_name='Error')), + ], + options={ + 'verbose_name': 'Change secret record', + 'ordering': ('-date_created',), + }, + ), + migrations.CreateModel( + name='GatheredAccount', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('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')), + ('present', models.BooleanField(default=True, verbose_name='Present')), + ('date_last_login', models.DateTimeField(null=True, verbose_name='Date login')), + ('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')), + ('address_last_login', models.CharField(default='', max_length=39, verbose_name='Address login')), + ], + options={ + 'verbose_name': 'Gather account automation', + 'ordering': ['asset'], + }, + ), + migrations.CreateModel( + name='HistoricalAccount', + fields=[ + ('id', models.UUIDField(db_index=True, default=uuid.uuid4)), + ('_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')), + ('version', models.IntegerField(default=0, verbose_name='Version')), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_date', models.DateTimeField(db_index=True)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), + ], + options={ + 'verbose_name': 'historical Account', + 'verbose_name_plural': 'historical Accounts', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': ('history_date', 'history_id'), + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + 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'), ('@SPEC', 'Specified account')], max_length=128, verbose_name='Alias')), + ('secret_from_login', models.BooleanField(default=None, null=True, verbose_name='Secret from login')), + ], + ), ] diff --git a/apps/accounts/migrations/0002_auto_20220616_0021.py b/apps/accounts/migrations/0002_auto_20220616_0021.py index cef9c230f..5befcf815 100644 --- a/apps/accounts/migrations/0002_auto_20220616_0021.py +++ b/apps/accounts/migrations/0002_auto_20220616_0021.py @@ -1,44 +1,102 @@ -# Generated by Django 3.2.14 on 2022-12-28 10:39 +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import common.db.encoder import common.db.fields -from django.conf import settings from django.db import migrations, models import django.db.models.deletion -import uuid class Migration(migrations.Migration): + + initial = True + dependencies = [ - ('assets', '0106_auto_20221228_1838'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('assets', '0001_initial'), ('accounts', '0001_initial'), ] operations = [ migrations.CreateModel( - name='AccountBackupAutomation', + name='AccountBaseAutomation', 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')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('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')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')), - ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')), - ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')), - ('types', models.JSONField(default=list)), - ('recipients', models.ManyToManyField(blank=True, related_name='recipient_escape_route_plans', - to=settings.AUTH_USER_MODEL, verbose_name='Recipient')), ], options={ - 'verbose_name': 'Account backup plan', - 'ordering': ['name'], - 'unique_together': {('name', 'org_id')}, + 'verbose_name': 'Account automation task', + 'proxy': True, + 'indexes': [], + 'constraints': [], }, - ) + bases=('assets.baseautomation',), + ), + migrations.CreateModel( + name='AutomationExecution', + fields=[ + ], + options={ + 'verbose_name': 'Automation execution', + 'verbose_name_plural': 'Automation executions', + 'permissions': [('view_changesecretexecution', 'Can view change secret execution'), ('add_changesecretexecution', 'Can add change secret execution'), ('view_gatheraccountsexecution', 'Can view gather accounts execution'), ('add_gatheraccountsexecution', 'Can add gather accounts execution'), ('view_pushaccountexecution', 'Can view push account execution'), ('add_pushaccountexecution', 'Can add push account execution')], + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('assets.automationexecution',), + ), + migrations.CreateModel( + name='ChangeSecretAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')), + ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_strategy', models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy')), + ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), + ('ssh_key_change_strategy', models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy')), + ], + options={ + 'verbose_name': 'Change secret automation', + }, + bases=('accounts.accountbaseautomation', models.Model), + ), + migrations.CreateModel( + name='GatherAccountsAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ('is_sync_account', models.BooleanField(blank=True, default=False, verbose_name='Is sync account')), + ], + options={ + 'verbose_name': 'Gather asset accounts', + }, + bases=('accounts.accountbaseautomation',), + ), + migrations.CreateModel( + name='PushAccountAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ('secret_type', models.CharField(choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, verbose_name='Secret type')), + ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), + ('secret_strategy', models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy')), + ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), + ('ssh_key_change_strategy', models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy')), + ('triggers', models.JSONField(default=list, max_length=16, verbose_name='Triggers')), + ('username', models.CharField(max_length=128, verbose_name='Username')), + ('action', models.CharField(max_length=16, verbose_name='Action')), + ], + options={ + 'verbose_name': 'Push asset account', + }, + bases=('accounts.accountbaseautomation', models.Model), + ), + migrations.CreateModel( + name='VerifyAccountAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ], + options={ + 'verbose_name': 'Verify asset account', + }, + bases=('accounts.accountbaseautomation',), + ), + migrations.AlterUniqueTogether( + name='virtualaccount', + unique_together={('alias', 'org_id')}, + ), ] diff --git a/apps/accounts/migrations/0003_automation.py b/apps/accounts/migrations/0003_automation.py index 4840cc2ad..0ab6c3a8b 100644 --- a/apps/accounts/migrations/0003_automation.py +++ b/apps/accounts/migrations/0003_automation.py @@ -1,198 +1,116 @@ -# Generated by Django 3.2.16 on 2022-12-30 08:08 +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import uuid - -import django.db.models.deletion from django.conf import settings from django.db import migrations, models - -import common.db.encoder -import common.db.fields +import django.db.models.deletion class Migration(migrations.Migration): + + initial = True + dependencies = [ - ('assets', '0107_automation'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('assets', '0001_initial'), + ('terminal', '0001_initial'), ('accounts', '0002_auto_20220616_0021'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.CreateModel( - name='AccountBaseAutomation', - fields=[ - ], - options={ - 'verbose_name': 'Account automation task', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.baseautomation',), + migrations.AddField( + model_name='historicalaccount', + name='history_user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), ), - migrations.CreateModel( - name='AutomationExecution', - fields=[ - ], - options={ - 'verbose_name': 'Automation execution', - 'verbose_name_plural': 'Automation executions', - 'permissions': [('view_changesecretexecution', 'Can view change secret execution'), - ('add_changesecretexecution', 'Can add change secret execution'), - ('view_gatheraccountsexecution', 'Can view gather accounts execution'), - ('add_gatheraccountsexecution', 'Can add gather accounts execution')], - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.automationexecution',), + migrations.AddField( + model_name='gatheredaccount', + name='asset', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.asset', verbose_name='Asset'), ), - migrations.CreateModel( - name='PushAccountAutomation', - fields=[ - ('baseautomation_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.baseautomation')), - ('secret_type', models.CharField( - choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, - verbose_name='Secret type')), - ('secret_strategy', models.CharField(choices=[('specific', 'Specific password'), - ('random_one', 'All assets use the same random password'), - ('random_all', - 'All assets use different random password')], - default='specific', max_length=16, - verbose_name='Secret strategy')), - ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), - ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), - ('ssh_key_change_strategy', models.CharField( - choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), - ('set_jms', 'Replace (The key generated by JumpServer) ')], default='add', max_length=16, - verbose_name='SSH key change strategy')), - ('triggers', models.JSONField(default=list, max_length=16, verbose_name='Triggers')), - ('username', models.CharField(max_length=128, verbose_name='Username')), - ('action', models.CharField(max_length=16, verbose_name='Action')), - ], - options={ - 'verbose_name': 'Push asset account', - }, - bases=('accounts.accountbaseautomation', models.Model), + migrations.AddField( + model_name='changesecretrecord', + name='account', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='accounts.account'), ), - - migrations.CreateModel( - name='GatherAccountsAutomation', - fields=[ - ('baseautomation_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.baseautomation')), - ], - options={ - 'verbose_name': 'Gather asset accounts', - }, - bases=('accounts.accountbaseautomation',), + migrations.AddField( + model_name='changesecretrecord', + name='asset', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.asset'), ), - migrations.CreateModel( - name='VerifyAccountAutomation', - fields=[ - ('baseautomation_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.baseautomation')), - ], - options={ - 'verbose_name': 'Verify asset account', - }, - bases=('accounts.accountbaseautomation',), + migrations.AddField( + model_name='changesecretrecord', + name='execution', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounts.automationexecution'), ), - migrations.CreateModel( - name='ChangeSecretRecord', - 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')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('old_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Old secret')), - ('new_secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='New secret')), - ('date_started', models.DateTimeField(blank=True, null=True, verbose_name='Date started')), - ('date_finished', models.DateTimeField(blank=True, null=True, verbose_name='Date finished')), - ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), - ('error', models.TextField(blank=True, null=True, verbose_name='Error')), - ('account', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='accounts.account')), - ('asset', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.asset')), - ('execution', - models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='accounts.automationexecution')), - ], - options={ - 'verbose_name': 'Change secret record', - }, + migrations.AddField( + model_name='accounttemplate', + name='platforms', + field=models.ManyToManyField(blank=True, related_name='account_templates', to='assets.platform', verbose_name='Platforms'), ), - migrations.CreateModel( - name='AccountBackupExecution', - fields=[ - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('date_start', models.DateTimeField(auto_now_add=True, verbose_name='Date start')), - ('timedelta', models.FloatField(default=0.0, null=True, verbose_name='Time')), - ('plan_snapshot', - models.JSONField(blank=True, default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True, - verbose_name='Account backup snapshot')), - ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], - default='manual', max_length=128, verbose_name='Trigger mode')), - ('reason', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Reason')), - ('is_success', models.BooleanField(default=False, verbose_name='Is success')), - ('plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='execution', - to='accounts.accountbackupautomation', verbose_name='Account backup plan')), - ], - options={ - 'verbose_name': 'Account backup execution', - 'ordering': ('-date_start',), - }, + migrations.AddField( + model_name='accounttemplate', + name='su_from', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='accounts.accounttemplate', verbose_name='Su from'), ), - migrations.CreateModel( - name='ChangeSecretAutomation', - fields=[ - ('baseautomation_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.baseautomation')), - ('secret_type', models.CharField( - choices=[('password', 'Password'), ('ssh_key', 'SSH key'), ('access_key', 'Access key'), - ('token', 'Token'), ('api_key', 'API key')], default='password', max_length=16, - verbose_name='Secret type')), - ('secret_strategy', models.CharField(choices=[('specific', 'Specific password'), - ('random_one', 'All assets use the same random password'), - ('random_all', - 'All assets use different random password')], - default='specific', max_length=16, - verbose_name='Secret strategy')), - ('secret', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Secret')), - ('password_rules', models.JSONField(default=dict, verbose_name='Password rules')), - ('ssh_key_change_strategy', models.CharField( - choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), - ('set_jms', 'Replace (The key generated by JumpServer) ')], default='add', max_length=16, - verbose_name='SSH key change strategy')), - ('recipients', - models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient')), - ], - options={ - 'verbose_name': 'Change secret automation', - }, - bases=('accounts.accountbaseautomation', models.Model), + migrations.AddField( + model_name='accountbackupexecution', + name='plan', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='execution', to='accounts.accountbackupautomation', verbose_name='Account backup plan'), ), - migrations.AlterModelOptions( - name='automationexecution', - options={'permissions': [('view_changesecretexecution', 'Can view change secret execution'), - ('add_changesecretexecution', 'Can add change secret execution'), - ('view_gatheraccountsexecution', 'Can view gather accounts execution'), - ('add_gatheraccountsexecution', 'Can add gather accounts execution'), - ('view_pushaccountexecution', 'Can view push account execution'), - ('add_pushaccountexecution', 'Can add push account execution')], - 'verbose_name': 'Automation execution', 'verbose_name_plural': 'Automation executions'}, + migrations.AddField( + model_name='accountbackupautomation', + name='obj_recipients_part_one', + field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_one_plans', to='terminal.replaystorage', verbose_name='Object storage recipient part one'), ), - migrations.AlterModelOptions( - name='changesecretrecord', - options={'ordering': ('-date_started',), 'verbose_name': 'Change secret record'}, + migrations.AddField( + model_name='accountbackupautomation', + name='obj_recipients_part_two', + field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_two_plans', to='terminal.replaystorage', verbose_name='Object storage recipient part two'), + ), + migrations.AddField( + model_name='accountbackupautomation', + name='recipients_part_one', + field=models.ManyToManyField(blank=True, related_name='recipient_part_one_plans', to=settings.AUTH_USER_MODEL, verbose_name='Recipient part one'), + ), + migrations.AddField( + model_name='accountbackupautomation', + name='recipients_part_two', + field=models.ManyToManyField(blank=True, related_name='recipient_part_two_plans', to=settings.AUTH_USER_MODEL, verbose_name='Recipient part two'), + ), + migrations.AddField( + model_name='account', + name='asset', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='accounts', to='assets.asset', verbose_name='Asset'), + ), + migrations.AddField( + model_name='account', + name='su_from', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='accounts.account', verbose_name='Su from'), + ), + migrations.AlterUniqueTogether( + name='gatheredaccount', + unique_together={('username', 'asset')}, + ), + migrations.AddField( + model_name='gatheraccountsautomation', + name='recipients', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient'), + ), + migrations.AddField( + model_name='changesecretautomation', + name='recipients', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient'), + ), + migrations.AlterUniqueTogether( + name='accounttemplate', + unique_together={('name', 'org_id')}, + ), + migrations.AlterUniqueTogether( + name='accountbackupautomation', + unique_together={('name', 'org_id')}, + ), + migrations.AlterUniqueTogether( + name='account', + unique_together={('name', 'asset'), ('username', 'asset', 'secret_type')}, ), ] diff --git a/apps/accounts/migrations/0004_auto_20230106_1507.py b/apps/accounts/migrations/0004_auto_20230106_1507.py deleted file mode 100644 index 6392fce3b..000000000 --- a/apps/accounts/migrations/0004_auto_20230106_1507.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.2.16 on 2023-01-06 07:07 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0003_automation'), - ] - - operations = [ - migrations.AlterField( - model_name='changesecretautomation', - name='secret_strategy', - field=models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy'), - ), - migrations.AlterField( - model_name='pushaccountautomation', - name='secret_strategy', - field=models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy'), - ), - ] diff --git a/apps/accounts/migrations/0005_alter_changesecretrecord_options.py b/apps/accounts/migrations/0005_alter_changesecretrecord_options.py deleted file mode 100644 index 67971198f..000000000 --- a/apps/accounts/migrations/0005_alter_changesecretrecord_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.16 on 2023-01-10 06:45 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0004_auto_20230106_1507'), - ] - - operations = [ - migrations.AlterModelOptions( - name='changesecretrecord', - options={'ordering': ('-date_created',), 'verbose_name': 'Change secret record'}, - ), - ] diff --git a/apps/accounts/migrations/0006_gatheredaccount.py b/apps/accounts/migrations/0006_gatheredaccount.py deleted file mode 100644 index f7058864e..000000000 --- a/apps/accounts/migrations/0006_gatheredaccount.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-07 04:41 - -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0108_alter_platform_charset'), - ('accounts', '0005_alter_changesecretrecord_options'), - ] - - operations = [ - migrations.CreateModel( - name='GatheredAccount', - 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')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('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')), - ('present', models.BooleanField(default=True, verbose_name='Present')), - ('date_last_login', models.DateTimeField(null=True, verbose_name='Date login')), - ('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')), - ('address_last_login', models.CharField(default='', max_length=39, verbose_name='Address login')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.asset', verbose_name='Asset')), - ], - options={ - 'verbose_name': 'Gather account', - 'ordering': ['asset'], - 'unique_together': {('username', 'asset')}, - }, - ), - ] diff --git a/apps/accounts/migrations/0007_alter_account_options.py b/apps/accounts/migrations/0007_alter_account_options.py deleted file mode 100644 index 6def6de6e..000000000 --- a/apps/accounts/migrations/0007_alter_account_options.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-16 11:07 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0006_gatheredaccount'), - ] - - operations = [ - migrations.AlterModelOptions( - name='account', - options={'permissions': [ - ('view_accountsecret', 'Can view asset account secret'), - ('view_historyaccount', 'Can view asset history account'), - ('view_historyaccountsecret', 'Can view asset history account secret'), - ('verify_account', 'Can verify account'), - ('push_account', 'Can push account'), - ('remove_account', 'Can remove account'), - ], 'verbose_name': 'Account'}, - ), - ] diff --git a/apps/accounts/migrations/0008_alter_gatheredaccount_options.py b/apps/accounts/migrations/0008_alter_gatheredaccount_options.py deleted file mode 100644 index d2600e700..000000000 --- a/apps/accounts/migrations/0008_alter_gatheredaccount_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-23 09:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0007_alter_account_options'), - ] - - operations = [ - migrations.AlterModelOptions( - name='gatheredaccount', - options={'ordering': ['asset'], 'verbose_name': 'Gather account automation'}, - ), - ] diff --git a/apps/accounts/migrations/0009_account_usernames_to_ids.py b/apps/accounts/migrations/0009_account_usernames_to_ids.py deleted file mode 100644 index 895176b4c..000000000 --- a/apps/accounts/migrations/0009_account_usernames_to_ids.py +++ /dev/null @@ -1,69 +0,0 @@ -# Generated by Django 3.2.16 on 2023-03-07 07:36 - -from django.db import migrations -from django.db.models import Q - - -def get_nodes_all_assets(apps, *nodes): - node_model = apps.get_model('assets', 'Node') - asset_model = apps.get_model('assets', 'Asset') - node_ids = set() - descendant_node_query = Q() - for n in nodes: - node_ids.add(n.id) - descendant_node_query |= Q(key__istartswith=f'{n.key}:') - if descendant_node_query: - _ids = node_model.objects.order_by().filter(descendant_node_query).values_list('id', flat=True) - node_ids.update(_ids) - return asset_model.objects.order_by().filter(nodes__id__in=node_ids).distinct() - - -def get_all_assets(apps, snapshot): - node_model = apps.get_model('assets', 'Node') - asset_model = apps.get_model('assets', 'Asset') - asset_ids = snapshot.get('assets', []) - node_ids = snapshot.get('nodes', []) - - nodes = node_model.objects.filter(id__in=node_ids) - node_asset_ids = get_nodes_all_assets(apps, *nodes).values_list('id', flat=True) - asset_ids = set(list(asset_ids) + list(node_asset_ids)) - return asset_model.objects.filter(id__in=asset_ids) - - -def migrate_account_usernames_to_ids(apps, schema_editor): - db_alias = schema_editor.connection.alias - execution_model = apps.get_model('accounts', 'AutomationExecution') - account_model = apps.get_model('accounts', 'Account') - executions = execution_model.objects.using(db_alias).all() - executions_update = [] - for execution in executions: - snapshot = execution.snapshot - accounts = account_model.objects.none() - account_usernames = snapshot.get('accounts', []) - for asset in get_all_assets(apps, snapshot): - accounts = accounts | asset.accounts.all() - secret_type = snapshot.get('secret_type') - if secret_type: - ids = accounts.filter( - username__in=account_usernames, - secret_type=secret_type - ).values_list('id', flat=True) - else: - ids = accounts.filter( - username__in=account_usernames - ).values_list('id', flat=True) - snapshot['accounts'] = [str(_id) for _id in ids] - execution.snapshot = snapshot - executions_update.append(execution) - - execution_model.objects.bulk_update(executions_update, ['snapshot']) - - -class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0008_alter_gatheredaccount_options'), - ] - - operations = [ - migrations.RunPython(migrate_account_usernames_to_ids), - ] diff --git a/apps/accounts/migrations/0010_gatheraccountsautomation_is_sync_account.py b/apps/accounts/migrations/0010_gatheraccountsautomation_is_sync_account.py deleted file mode 100644 index 259497692..000000000 --- a/apps/accounts/migrations/0010_gatheraccountsautomation_is_sync_account.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.2.16 on 2023-03-23 08:39 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0009_account_usernames_to_ids'), - ] - - operations = [ - migrations.AddField( - model_name='gatheraccountsautomation', - name='is_sync_account', - field=models.BooleanField(blank=True, default=False, verbose_name='Is sync account'), - ), - migrations.AddField( - model_name='account', - name='source_id', - field=models.CharField(max_length=128, null=True, blank=True, verbose_name='Source ID'), - ), - ] diff --git a/apps/accounts/migrations/0011_auto_20230506_1443.py b/apps/accounts/migrations/0011_auto_20230506_1443.py deleted file mode 100644 index 3460376bd..000000000 --- a/apps/accounts/migrations/0011_auto_20230506_1443.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.2.17 on 2023-05-06 06:43 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0010_gatheraccountsautomation_is_sync_account'), - ] - - operations = [ - migrations.AddField( - model_name='accounttemplate', - name='su_from', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='accounts.accounttemplate', verbose_name='Su from'), - ), - migrations.AlterField( - model_name='changesecretautomation', - name='ssh_key_change_strategy', - field=models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy'), - ), - migrations.AlterField( - model_name='pushaccountautomation', - name='ssh_key_change_strategy', - field=models.CharField(choices=[('add', 'Append SSH KEY'), ('set', 'Empty and append SSH KEY'), ('set_jms', 'Replace (Replace only keys pushed by JumpServer) ')], default='add', max_length=16, verbose_name='SSH key change strategy'), - ), - ] diff --git a/apps/accounts/migrations/0012_auto_20230621_1456.py b/apps/accounts/migrations/0012_auto_20230621_1456.py deleted file mode 100644 index 389e2b63d..000000000 --- a/apps/accounts/migrations/0012_auto_20230621_1456.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-21 06:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0011_auto_20230506_1443'), - ] - - operations = [ - migrations.RenameField( - model_name='account', - old_name='secret', - new_name='_secret', - ), - migrations.RenameField( - model_name='accounttemplate', - old_name='secret', - new_name='_secret', - ), - migrations.RenameField( - model_name='historicalaccount', - old_name='secret', - new_name='_secret', - ), - ] diff --git a/apps/accounts/migrations/0013_account_backup_recipients.py b/apps/accounts/migrations/0013_account_backup_recipients.py deleted file mode 100644 index 6fe03e349..000000000 --- a/apps/accounts/migrations/0013_account_backup_recipients.py +++ /dev/null @@ -1,77 +0,0 @@ -# Generated by Django 4.1.10 on 2023-08-03 08:28 -from django.conf import settings -from django.db import migrations, models - -import common.db.encoder - - -def migrate_recipients(apps, schema_editor): - account_backup_model = apps.get_model('accounts', 'AccountBackupAutomation') - execution_model = apps.get_model('accounts', 'AccountBackupExecution') - for account_backup in account_backup_model.objects.all(): - recipients = list(account_backup.recipients.all()) - if not recipients: - continue - account_backup.recipients_part_one.set(recipients) - - objs = [] - for execution in execution_model.objects.all(): - snapshot = execution.snapshot - recipients = snapshot.pop('recipients', {}) - snapshot.update({'recipients_part_one': recipients, 'recipients_part_two': {}}) - objs.append(execution) - execution_model.objects.bulk_update(objs, ['snapshot']) - - -def migrate_snapshot(apps, schema_editor): - model = apps.get_model('accounts', 'AccountBackupExecution') - objs = [] - for execution in model.objects.all(): - execution.snapshot = execution.plan_snapshot - objs.append(execution) - model.objects.bulk_update(objs, ['snapshot']) - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('accounts', '0012_auto_20230621_1456'), - ] - - operations = [ - migrations.AddField( - model_name='accountbackupautomation', - name='recipients_part_one', - field=models.ManyToManyField( - blank=True, related_name='recipient_part_one_plans', - to=settings.AUTH_USER_MODEL, verbose_name='Recipient part one' - ), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='recipients_part_two', - field=models.ManyToManyField( - blank=True, related_name='recipient_part_two_plans', - to=settings.AUTH_USER_MODEL, verbose_name='Recipient part two' - ), - ), - migrations.AddField( - model_name='accountbackupexecution', - name='snapshot', - field=models.JSONField( - default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, - null=True, blank=True, verbose_name='Account backup snapshot' - ), - ), - migrations.RunPython(migrate_snapshot), - migrations.RunPython(migrate_recipients), - migrations.RemoveField( - model_name='accountbackupexecution', - name='plan_snapshot', - ), - migrations.RemoveField( - model_name='accountbackupautomation', - name='recipients', - ), - - ] diff --git a/apps/accounts/migrations/0014_virtualaccount.py b/apps/accounts/migrations/0014_virtualaccount.py deleted file mode 100644 index df0159fc9..000000000 --- a/apps/accounts/migrations/0014_virtualaccount.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 4.1.10 on 2023-08-01 09:12 - -import uuid - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0013_account_backup_recipients'), - ] - - 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'), ('@SPEC', 'Specified 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/migrations/0015_auto_20230825_1120.py b/apps/accounts/migrations/0015_auto_20230825_1120.py deleted file mode 100644 index 533613855..000000000 --- a/apps/accounts/migrations/0015_auto_20230825_1120.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 4.1.10 on 2023-08-25 03:19 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0122_auto_20230803_1553'), - ('accounts', '0014_virtualaccount'), - ] - - operations = [ - migrations.AddField( - model_name='accounttemplate', - name='auto_push', - field=models.BooleanField(default=False, verbose_name='Auto push'), - ), - migrations.AddField( - model_name='accounttemplate', - name='platforms', - field=models.ManyToManyField(related_name='account_templates', to='assets.platform', verbose_name='Platforms', blank=True), - ), - migrations.AddField( - model_name='accounttemplate', - name='push_params', - field=models.JSONField(default=dict, verbose_name='Push params'), - ), - migrations.AddField( - model_name='accounttemplate', - name='secret_strategy', - field=models.CharField(choices=[('specific', 'Specific secret'), ('random', 'Random generate')], default='specific', max_length=16, verbose_name='Secret strategy'), - ), - ] diff --git a/apps/accounts/migrations/0016_accounttemplate_password_rules.py b/apps/accounts/migrations/0016_accounttemplate_password_rules.py deleted file mode 100644 index d036f90a4..000000000 --- a/apps/accounts/migrations/0016_accounttemplate_password_rules.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-18 08:09 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0015_auto_20230825_1120'), - ] - - operations = [ - migrations.AddField( - model_name='accounttemplate', - name='password_rules', - field=models.JSONField(default=dict, verbose_name='Password rules'), - ), - ] diff --git a/apps/accounts/migrations/0017_alter_automationexecution_options.py b/apps/accounts/migrations/0017_alter_automationexecution_options.py deleted file mode 100644 index a1f9f4dbb..000000000 --- a/apps/accounts/migrations/0017_alter_automationexecution_options.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-24 05:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0016_accounttemplate_password_rules'), - ] - - operations = [ - migrations.AlterModelOptions( - name='automationexecution', - options={ - 'permissions': [ - ('view_changesecretexecution', 'Can view change secret execution'), - ('add_changesecretexecution', 'Can add change secret execution'), - ('view_gatheraccountsexecution', 'Can view gather accounts execution'), - ('add_gatheraccountsexecution', 'Can add gather accounts execution'), - ('view_pushaccountexecution', 'Can view push account execution'), - ('add_pushaccountexecution', 'Can add push account execution') - ], - 'verbose_name': 'Automation execution', 'verbose_name_plural': 'Automation executions'}, - ), - ] diff --git a/apps/accounts/migrations/0018_accountbackupautomation_backup_type_and_more.py b/apps/accounts/migrations/0018_accountbackupautomation_backup_type_and_more.py deleted file mode 100644 index e7e04fb24..000000000 --- a/apps/accounts/migrations/0018_accountbackupautomation_backup_type_and_more.py +++ /dev/null @@ -1,45 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-03 07:10 - -import common.db.fields -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0067_alter_replaystorage_type'), - ('accounts', '0017_alter_automationexecution_options'), - ] - - operations = [ - migrations.AddField( - model_name='accountbackupautomation', - name='backup_type', - field=models.CharField(choices=[('email', 'Email'), ('object_storage', 'Object Storage')], default='email', max_length=128), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='is_password_divided_by_email', - field=models.BooleanField(default=True), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='is_password_divided_by_obj_storage', - field=models.BooleanField(default=True), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='obj_recipients_part_one', - field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_one_plans', to='terminal.replaystorage', verbose_name='Object Storage Recipient part one'), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='obj_recipients_part_two', - field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_two_plans', to='terminal.replaystorage', verbose_name='Object Storage Recipient part two'), - ), - migrations.AddField( - model_name='accountbackupautomation', - name='zip_encrypt_password', - field=common.db.fields.EncryptCharField(blank=True, max_length=4096, null=True, verbose_name='Zip Encrypt Password'), - ), - ] diff --git a/apps/accounts/migrations/0019_gatheraccountsautomation_recipients.py b/apps/accounts/migrations/0019_gatheraccountsautomation_recipients.py deleted file mode 100644 index fa190f8ac..000000000 --- a/apps/accounts/migrations/0019_gatheraccountsautomation_recipients.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-31 06:12 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('accounts', '0018_accountbackupautomation_backup_type_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='gatheraccountsautomation', - name='recipients', - field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Recipient'), - ), - ] diff --git a/apps/accounts/migrations/0020_alter_accountbackupautomation_backup_type_and_more.py b/apps/accounts/migrations/0020_alter_accountbackupautomation_backup_type_and_more.py deleted file mode 100644 index dda414f94..000000000 --- a/apps/accounts/migrations/0020_alter_accountbackupautomation_backup_type_and_more.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-16 02:13 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0019_gatheraccountsautomation_recipients'), - ] - - operations = [ - migrations.AlterField( - model_name='accountbackupautomation', - name='backup_type', - field=models.CharField(choices=[('email', 'Email'), ('object_storage', 'SFTP')], default='email', max_length=128, verbose_name='Backup Type'), - ), - migrations.AlterField( - model_name='accountbackupautomation', - name='is_password_divided_by_email', - field=models.BooleanField(default=True, verbose_name='Password divided'), - ), - migrations.AlterField( - model_name='accountbackupautomation', - name='is_password_divided_by_obj_storage', - field=models.BooleanField(default=True, verbose_name='Password divided'), - ), - ] diff --git a/apps/acls/migrations/0001_initial.py b/apps/acls/migrations/0001_initial.py index 3d314387b..673386dc5 100644 --- a/apps/acls/migrations/0001_initial.py +++ b/apps/acls/migrations/0001_initial.py @@ -1,75 +1,129 @@ -# Generated by Django 3.1 on 2021-03-11 09:53 - -import uuid +# Generated by Django 4.1.13 on 2024-05-09 03:16 +import common.db.fields import django.core.validators -import django.db.models.deletion -from django.conf import settings from django.db import migrations, models +import uuid class Migration(migrations.Migration): + initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( - name='LoginACL', + name='CommandFilterACL', fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), + ('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')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', - validators=[django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(100)], - verbose_name='Priority')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('ip_group', models.JSONField(default=list, verbose_name='Login IP')), - ('action', - models.CharField(choices=[('reject', 'Reject'), ('allow', 'Allow')], default='reject', max_length=64, - verbose_name='Action')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='login_acls', - to=settings.AUTH_USER_MODEL, verbose_name='User')), + ('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')), + ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), + ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('assets', common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets')), + ('accounts', models.JSONField(default=list, verbose_name='Accounts')), ], options={ + 'verbose_name': 'Command acl', 'ordering': ('priority', '-is_active', 'name'), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='CommandGroup', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('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')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('type', models.CharField(choices=[('command', 'Command'), ('regex', 'Regex')], default='command', max_length=16, verbose_name='Type')), + ('content', models.TextField(help_text='One line one command', verbose_name='Content')), + ('ignore_case', models.BooleanField(default=True, verbose_name='Ignore case')), + ], + options={ + 'verbose_name': 'Command group', + }, + ), + migrations.CreateModel( + name='ConnectMethodACL', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), + ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')), + ('connect_methods', models.JSONField(default=list, verbose_name='Connect methods')), + ], + options={ + 'verbose_name': 'Connect method acl', + 'ordering': ('priority', '-is_active', 'name'), + 'abstract': False, + }, + ), + migrations.CreateModel( + name='LoginACL', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), + ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')), + ('rules', models.JSONField(default=dict, verbose_name='Rule')), + ], + options={ + 'verbose_name': 'Login acl', + 'ordering': ('priority', '-is_active', 'name'), + 'abstract': False, }, ), migrations.CreateModel( name='LoginAssetACL', fields=[ - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), + ('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')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', - validators=[django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(100)], - verbose_name='Priority')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('users', models.JSONField(verbose_name='User')), - ('system_users', models.JSONField(verbose_name='System User')), - ('assets', models.JSONField(verbose_name='Asset')), - ('action', - models.CharField(choices=[('login_confirm', 'Login confirm')], default='login_confirm', max_length=64, - verbose_name='Action')), - ('reviewers', - models.ManyToManyField(blank=True, related_name='review_login_asset_acls', to=settings.AUTH_USER_MODEL, - verbose_name='Reviewers')), + ('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')), + ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), + ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('assets', common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets')), + ('accounts', models.JSONField(default=list, verbose_name='Accounts')), + ('rules', models.JSONField(default=dict, verbose_name='Rule')), ], options={ + 'verbose_name': 'Login asset acl', 'ordering': ('priority', '-is_active', 'name'), - 'unique_together': {('name', 'org_id')}, + 'abstract': False, }, ), ] diff --git a/apps/acls/migrations/0002_auto_20210926_1047.py b/apps/acls/migrations/0002_auto_20210926_1047.py index f2019a613..281bb758f 100644 --- a/apps/acls/migrations/0002_auto_20210926_1047.py +++ b/apps/acls/migrations/0002_auto_20210926_1047.py @@ -1,98 +1,54 @@ -# Generated by Django 3.1.12 on 2021-09-26 02:47 -import django +# Generated by Django 4.1.13 on 2024-05-09 03:16 + from django.conf import settings -from django.db import migrations, models, transaction - -LOGIN_CONFIRM_ZH = '登录复核' -LOGIN_CONFIRM_EN = 'Login confirm' - -DEFAULT_TIME_PERIODS = [{'id': i, 'value': '00:00~00:00'} for i in range(7)] - - -def has_zh(name: str) -> bool: - for i in name: - if u'\u4e00' <= i <= u'\u9fff': - return True - return False - - -def migrate_login_confirm(apps, schema_editor): - login_acl_model = apps.get_model("acls", "LoginACL") - login_confirm_model = apps.get_model("authentication", "LoginConfirmSetting") - - with transaction.atomic(): - for instance in login_confirm_model.objects.filter(is_active=True): - user = instance.user - reviewers = instance.reviewers.all() - login_confirm = LOGIN_CONFIRM_ZH if has_zh(user.name) else LOGIN_CONFIRM_EN - date_created = instance.date_created.strftime('%Y-%m-%d %H:%M:%S') - if reviewers.count() == 0: - continue - data = { - - 'user': user, - 'name': f'{user.name}-{login_confirm} ({date_created})', - 'created_by': instance.created_by, - 'action': 'confirm', - 'rules': {'ip_group': ['*'], 'time_period': DEFAULT_TIME_PERIODS} - } - instance = login_acl_model.objects.create(**data) - instance.reviewers.set(reviewers) - - -def migrate_ip_group(apps, schema_editor): - login_acl_model = apps.get_model("acls", "LoginACL") - updates = list() - with transaction.atomic(): - for instance in login_acl_model.objects.exclude(action='confirm'): - instance.rules = {'ip_group': instance.ip_group, 'time_period': DEFAULT_TIME_PERIODS} - updates.append(instance) - login_acl_model.objects.bulk_update(updates, ['rules', ]) +from django.db import migrations, models class Migration(migrations.Migration): + + initial = True + dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('acls', '0001_initial'), - ('authentication', '0004_ssotoken'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.AlterField( - model_name='loginacl', - name='action', - field=models.CharField(choices=[('reject', 'Reject'), ('allow', 'Allow'), ('confirm', 'Login confirm')], - default='reject', max_length=64, verbose_name='Action'), + migrations.AddField( + model_name='loginassetacl', + name='reviewers', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), ), migrations.AddField( model_name='loginacl', name='reviewers', - field=models.ManyToManyField(blank=True, related_name='login_confirm_acls', - to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), - ), - migrations.AlterField( - model_name='loginacl', - name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, - related_name='login_acls', to=settings.AUTH_USER_MODEL, verbose_name='User'), + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), ), migrations.AddField( - model_name='loginacl', - name='rules', - field=models.JSONField(default=dict, verbose_name='Rule'), + model_name='connectmethodacl', + name='reviewers', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), ), - migrations.RunPython(migrate_login_confirm), - migrations.RunPython(migrate_ip_group), - migrations.RemoveField( - model_name='loginacl', - name='ip_group', + migrations.AlterUniqueTogether( + name='commandgroup', + unique_together={('org_id', 'name')}, ), - migrations.AlterModelOptions( - name='loginacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login acl'}, + migrations.AddField( + model_name='commandfilteracl', + name='command_groups', + field=models.ManyToManyField(related_name='command_filters', to='acls.commandgroup', verbose_name='Command group'), ), - migrations.AlterModelOptions( + migrations.AddField( + model_name='commandfilteracl', + name='reviewers', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), + ), + migrations.AlterUniqueTogether( name='loginassetacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login asset acl'}, + unique_together={('name', 'org_id')}, + ), + migrations.AlterUniqueTogether( + name='commandfilteracl', + unique_together={('name', 'org_id')}, ), ] diff --git a/apps/acls/migrations/0003_auto_20211130_1037.py b/apps/acls/migrations/0003_auto_20211130_1037.py deleted file mode 100644 index 9a975c684..000000000 --- a/apps/acls/migrations/0003_auto_20211130_1037.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 3.1.13 on 2021-11-30 02:37 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0002_auto_20210926_1047'), - ] - - operations = [ - migrations.AlterModelOptions( - name='loginacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login acl'}, - ), - migrations.AlterModelOptions( - name='loginassetacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login asset acl'}, - ), - ] diff --git a/apps/acls/migrations/0004_auto_20220831_1658.py b/apps/acls/migrations/0004_auto_20220831_1658.py deleted file mode 100644 index 6fd1ef86b..000000000 --- a/apps/acls/migrations/0004_auto_20220831_1658.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.2.13 on 2022-08-31 08:58 - -from django.db import migrations, models - - -def migrate_system_users_to_accounts(apps, schema_editor): - login_asset_acl_model = apps.get_model('acls', 'LoginAssetACL') - qs = login_asset_acl_model.objects.all() - login_asset_acls = [] - for instance in qs: - instance.accounts = instance.system_users - login_asset_acls.append(instance) - login_asset_acl_model.objects.bulk_update(login_asset_acls, ['accounts']) - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0003_auto_20211130_1037'), - ] - - operations = [ - migrations.AddField( - model_name='loginassetacl', - name='accounts', - field=models.JSONField(verbose_name='Account'), - ), - migrations.RunPython(migrate_system_users_to_accounts), - migrations.RemoveField( - model_name='loginassetacl', - name='system_users', - ), - - ] diff --git a/apps/acls/migrations/0005_auto_20221201_1846.py b/apps/acls/migrations/0005_auto_20221201_1846.py deleted file mode 100644 index 4885ea97e..000000000 --- a/apps/acls/migrations/0005_auto_20221201_1846.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-01 10:46 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('acls', '0004_auto_20220831_1658'), - ] - - operations = [ - migrations.AlterField( - model_name='loginacl', - name='action', - field=models.CharField(default='reject', max_length=64, verbose_name='Action'), - ), - migrations.AlterField( - model_name='loginacl', - name='reviewers', - field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), - ), - migrations.AlterField( - model_name='loginassetacl', - name='action', - field=models.CharField(default='reject', max_length=64, verbose_name='Action'), - ), - migrations.AlterField( - model_name='loginassetacl', - name='reviewers', - field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), - ), - ] diff --git a/apps/acls/migrations/0006_commandfilteracl_commandgroup.py b/apps/acls/migrations/0006_commandfilteracl_commandgroup.py deleted file mode 100644 index 3c1bd6793..000000000 --- a/apps/acls/migrations/0006_commandfilteracl_commandgroup.py +++ /dev/null @@ -1,70 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-01 11:39 - -import uuid - -import django.core.validators -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('acls', '0005_auto_20221201_1846'), - ] - - operations = [ - migrations.CreateModel( - name='CommandGroup', - fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('type', models.CharField(choices=[('command', 'Command'), ('regex', 'Regex')], default='command', - max_length=16, verbose_name='Type')), - ('content', models.TextField(help_text='One line one command', verbose_name='Content')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('ignore_case', models.BooleanField(default=True, verbose_name='Ignore case')), - ], - options={ - 'verbose_name': 'Command filter rule', - 'unique_together': {('org_id', 'name')}, - }, - ), - migrations.CreateModel( - name='CommandFilterACL', - fields=[ - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', - validators=[django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(100)], - verbose_name='Priority')), - ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('users', models.JSONField(verbose_name='User')), - ('accounts', models.JSONField(verbose_name='Account')), - ('assets', models.JSONField(verbose_name='Asset')), - ('commands', models.ManyToManyField(to='acls.CommandGroup', verbose_name='Commands')), - ( - 'reviewers', - models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers')), - ], - options={ - 'verbose_name': 'Command acl', - 'ordering': ('priority', '-is_active', 'name'), - 'unique_together': {('name', 'org_id')}, - }, - ), - ] diff --git a/apps/acls/migrations/0007_auto_20221202_1048.py b/apps/acls/migrations/0007_auto_20221202_1048.py deleted file mode 100644 index 1a61a4ff4..000000000 --- a/apps/acls/migrations/0007_auto_20221202_1048.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-02 02:48 - -from django.db import migrations - - -def migrate_login_type(apps, schema_editor): - login_asset_model = apps.get_model('acls', 'LoginAssetACL') - login_asset_model.objects.filter(action='login_confirm').update(action='review') - - login_system_model = apps.get_model('acls', 'LoginACL') - login_system_model.objects.filter(action='confirm').update(action='review') - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0006_commandfilteracl_commandgroup'), - ] - - operations = [ - migrations.RunPython(migrate_login_type), - ] diff --git a/apps/acls/migrations/0008_commandgroup_comment.py b/apps/acls/migrations/0008_commandgroup_comment.py deleted file mode 100644 index 0764daa22..000000000 --- a/apps/acls/migrations/0008_commandgroup_comment.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-02 04:25 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0007_auto_20221202_1048'), - ] - - operations = [ - migrations.AlterModelOptions( - name='commandgroup', - options={'verbose_name': 'Command group'}, - ), - migrations.RenameField( - model_name='commandfilteracl', - old_name='commands', - new_name='command_groups', - ), - migrations.AlterModelOptions( - name='commandfilteracl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Command acl'}, - ), - migrations.AlterModelOptions( - name='loginacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login acl'}, - ), - migrations.AlterModelOptions( - name='loginassetacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Login asset acl'}, - ), - ] diff --git a/apps/acls/migrations/0009_auto_20221220_1956.py b/apps/acls/migrations/0009_auto_20221220_1956.py deleted file mode 100644 index 78f8b1152..000000000 --- a/apps/acls/migrations/0009_auto_20221220_1956.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('acls', '0008_commandgroup_comment'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilteracl', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='loginacl', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='loginassetacl', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='commandfilteracl', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='commandgroup', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='commandgroup', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='loginacl', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='loginassetacl', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - ] diff --git a/apps/acls/migrations/0010_alter_commandfilteracl_command_groups.py b/apps/acls/migrations/0010_alter_commandfilteracl_command_groups.py deleted file mode 100644 index b657906f1..000000000 --- a/apps/acls/migrations/0010_alter_commandfilteracl_command_groups.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.16 on 2023-01-10 06:45 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('acls', '0009_auto_20221220_1956'), - ] - - operations = [ - migrations.AlterField( - model_name='commandfilteracl', - name='command_groups', - field=models.ManyToManyField(to='acls.CommandGroup', verbose_name='Command group'), - ), - ] diff --git a/apps/acls/migrations/0011_auto_20230425_1704.py b/apps/acls/migrations/0011_auto_20230425_1704.py deleted file mode 100644 index f5d7dee6c..000000000 --- a/apps/acls/migrations/0011_auto_20230425_1704.py +++ /dev/null @@ -1,44 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-25 09:04 - -from django.db import migrations, models - -import common.db.fields - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0010_alter_commandfilteracl_command_groups'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilteracl', - name='new_accounts', - field=models.JSONField(default=list, verbose_name='Accounts'), - ), - migrations.AddField( - model_name='commandfilteracl', - name='new_assets', - field=common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets'), - ), - migrations.AddField( - model_name='commandfilteracl', - name='new_users', - field=common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users'), - ), - migrations.AddField( - model_name='loginassetacl', - name='new_accounts', - field=models.JSONField(default=list, verbose_name='Accounts') - ), - migrations.AddField( - model_name='loginassetacl', - name='new_assets', - field=common.db.fields.JSONManyToManyField(default=dict, to='assets.Asset', verbose_name='Assets'), - ), - migrations.AddField( - model_name='loginassetacl', - name='new_users', - field=common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users'), - ), - ] diff --git a/apps/acls/migrations/0012_auto_20230426_1111.py b/apps/acls/migrations/0012_auto_20230426_1111.py deleted file mode 100644 index c0e225138..000000000 --- a/apps/acls/migrations/0012_auto_20230426_1111.py +++ /dev/null @@ -1,41 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-26 03:11 - -from django.db import migrations - - -def migrate_base_acl_users_assets_accounts(apps, *args): - cmd_acl_model = apps.get_model('acls', 'CommandFilterACL') - login_asset_acl_model = apps.get_model('acls', 'LoginAssetACL') - - for model in [cmd_acl_model, login_asset_acl_model]: - for obj in model.objects.all(): - user_names = (obj.users or {}).get('username_group', []) - obj.new_users = { - "type": "attrs", - "attrs": [{"name": "username", "value": user_names, "match": "in"}] - } - - asset_names = (obj.assets or {}).get('name_group', []) - asset_attrs = [] - if asset_names: - asset_attrs.append({"name": "name", "value": asset_names, "match": "in"}) - asset_address = (obj.assets or {}).get('address_group', []) - if asset_address: - asset_attrs.append({"name": "address", "value": asset_address, "match": "ip_in"}) - obj.new_assets = {"type": "attrs", "attrs": asset_attrs} - - account_usernames = (obj.accounts or {}).get('username_group', []) - if '*' in account_usernames: - account_usernames = ['@ALL'] - obj.new_accounts = account_usernames - obj.save() - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0011_auto_20230425_1704'), - ] - - operations = [ - migrations.RunPython(migrate_base_acl_users_assets_accounts) - ] diff --git a/apps/acls/migrations/0013_auto_20230426_1759.py b/apps/acls/migrations/0013_auto_20230426_1759.py deleted file mode 100644 index 56dd58446..000000000 --- a/apps/acls/migrations/0013_auto_20230426_1759.py +++ /dev/null @@ -1,66 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-26 09:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0012_auto_20230426_1111'), - ] - - operations = [ - migrations.RemoveField( - model_name='commandfilteracl', - name='accounts', - ), - migrations.RemoveField( - model_name='commandfilteracl', - name='assets', - ), - migrations.RemoveField( - model_name='commandfilteracl', - name='users', - ), - migrations.RemoveField( - model_name='loginassetacl', - name='accounts', - ), - migrations.RemoveField( - model_name='loginassetacl', - name='assets', - ), - migrations.RemoveField( - model_name='loginassetacl', - name='users', - ), - migrations.RenameField( - model_name='commandfilteracl', - old_name='new_accounts', - new_name='accounts', - ), - migrations.RenameField( - model_name='commandfilteracl', - old_name='new_assets', - new_name='assets', - ), - migrations.RenameField( - model_name='commandfilteracl', - old_name='new_users', - new_name='users', - ), - migrations.RenameField( - model_name='loginassetacl', - old_name='new_accounts', - new_name='accounts', - ), - migrations.RenameField( - model_name='loginassetacl', - old_name='new_assets', - new_name='assets', - ), - migrations.RenameField( - model_name='loginassetacl', - old_name='new_users', - new_name='users', - ), - ] diff --git a/apps/acls/migrations/0014_loginassetacl_rules.py b/apps/acls/migrations/0014_loginassetacl_rules.py deleted file mode 100644 index d7574ffd0..000000000 --- a/apps/acls/migrations/0014_loginassetacl_rules.py +++ /dev/null @@ -1,18 +0,0 @@ -# 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'), - ), - ] diff --git a/apps/acls/migrations/0015_connectmethodacl.py b/apps/acls/migrations/0015_connectmethodacl.py deleted file mode 100644 index 5d5e3ff8c..000000000 --- a/apps/acls/migrations/0015_connectmethodacl.py +++ /dev/null @@ -1,46 +0,0 @@ -# Generated by Django 3.2.17 on 2023-06-06 06:23 - -import uuid - -import django.core.validators -from django.conf import settings -from django.db import migrations, models - -import common.db.fields - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('acls', '0014_loginassetacl_rules'), - ] - - operations = [ - migrations.CreateModel( - name='ConnectMethodACL', - 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')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('priority', models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', - validators=[django.core.validators.MinValueValidator(1), - django.core.validators.MaxValueValidator(100)], - verbose_name='Priority')), - ('action', models.CharField(default='reject', max_length=64, verbose_name='Action')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), - ('users', common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users')), - ('connect_methods', models.JSONField(default=list, verbose_name='Connect methods')), - ( - 'reviewers', - models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Reviewers')), - ], - options={ - 'ordering': ('priority', '-is_active', 'name'), - 'abstract': False, - }, - ), - ] diff --git a/apps/acls/migrations/0016_auto_20230606_1857.py b/apps/acls/migrations/0016_auto_20230606_1857.py deleted file mode 100644 index d703dac52..000000000 --- a/apps/acls/migrations/0016_auto_20230606_1857.py +++ /dev/null @@ -1,47 +0,0 @@ -# Generated by Django 3.2.17 on 2023-06-06 10:57 - -from django.db import migrations, models - -import common.db.fields - - -def migrate_users_login_acls(apps, schema_editor): - login_acl_model = apps.get_model('acls', 'LoginACL') - - name_used = [] - login_acls = [] - for login_acl in login_acl_model.objects.all().select_related('user'): - name = '{}_{}'.format(login_acl.name, login_acl.user.username) - if name.lower() in name_used: - name += '_{}'.format(str(login_acl.user_id)[:4]) - name_used.append(name.lower()) - login_acl.name = name - login_acl.users = { - "type": "ids", "ids": [str(login_acl.user_id)] - } - login_acls.append(login_acl) - login_acl_model.objects.bulk_update(login_acls, ['name', 'users']) - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0015_connectmethodacl'), - ] - - operations = [ - migrations.AddField( - model_name='loginacl', - name='users', - field=common.db.fields.JSONManyToManyField(default=dict, to='users.User', verbose_name='Users'), - ), - migrations.RunPython(migrate_users_login_acls), - migrations.RemoveField( - model_name='loginacl', - name='user', - ), - migrations.AlterField( - model_name='loginacl', - name='name', - field=models.CharField(max_length=128, unique=True, verbose_name='Name'), - ), - ] diff --git a/apps/acls/migrations/0017_alter_connectmethodacl_options.py b/apps/acls/migrations/0017_alter_connectmethodacl_options.py deleted file mode 100644 index 6767771d6..000000000 --- a/apps/acls/migrations/0017_alter_connectmethodacl_options.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-13 07:49 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0016_auto_20230606_1857'), - ] - - operations = [ - migrations.AlterModelOptions( - name='connectmethodacl', - options={'ordering': ('priority', '-is_active', 'name'), 'verbose_name': 'Connect method acl'}, - ), - ] diff --git a/apps/acls/migrations/0018_alter_commandfilteracl_command_groups.py b/apps/acls/migrations/0018_alter_commandfilteracl_command_groups.py deleted file mode 100644 index 0dea952a8..000000000 --- a/apps/acls/migrations/0018_alter_commandfilteracl_command_groups.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-18 10:44 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('acls', '0017_alter_connectmethodacl_options'), - ] - - operations = [ - migrations.AlterField( - model_name='commandfilteracl', - name='command_groups', - field=models.ManyToManyField(related_name='command_filters', to='acls.commandgroup', verbose_name='Command group'), - ), - ] diff --git a/apps/applications/__init__.py b/apps/applications/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/applications/api/application.py b/apps/applications/api/application.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/applications/apps.py b/apps/applications/apps.py deleted file mode 100644 index 888e4739f..000000000 --- a/apps/applications/apps.py +++ /dev/null @@ -1,12 +0,0 @@ -from __future__ import unicode_literals - -from django.apps import AppConfig -from django.utils.translation import gettext_lazy as _ - - -class ApplicationsConfig(AppConfig): - name = 'applications' - verbose_name = _('App Applications') - - def ready(self): - super().ready() diff --git a/apps/applications/migrations/0001_initial.py b/apps/applications/migrations/0001_initial.py deleted file mode 100644 index 26948fc73..000000000 --- a/apps/applications/migrations/0001_initial.py +++ /dev/null @@ -1,42 +0,0 @@ -# Generated by Django 2.1.7 on 2019-05-20 11:04 - -import common.db.fields -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('assets', '0026_auto_20190325_2035'), - ] - - operations = [ - migrations.CreateModel( - name='RemoteApp', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('type', models.CharField(choices=[('Browser', (('chrome', 'Chrome'),)), ('Database tools', (('mysql_workbench', 'MySQL Workbench'),)), ('Virtualization tools', (('vmware_client', 'vSphere Client'),)), ('custom', 'Custom')], default='chrome', max_length=128, verbose_name='App type')), - ('path', models.CharField(max_length=128, verbose_name='App path')), - ('params', common.db.fields.EncryptJsonDictTextField(blank=True, default={}, max_length=4096, null=True, verbose_name='Parameters')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset', verbose_name='Asset')), - ('system_user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.SystemUser', verbose_name='System user')), - ], - options={ - 'verbose_name': 'RemoteApp', - 'ordering': ('name',), - }, - ), - migrations.AlterUniqueTogether( - name='remoteapp', - unique_together={('org_id', 'name')}, - ), - ] diff --git a/apps/applications/migrations/0002_remove_remoteapp_system_user.py b/apps/applications/migrations/0002_remove_remoteapp_system_user.py deleted file mode 100644 index 03b320752..000000000 --- a/apps/applications/migrations/0002_remove_remoteapp_system_user.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-09 09:57 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0001_initial'), - ('perms', '0009_remoteapppermission_system_users'), - ] - - operations = [ - migrations.RemoveField( - model_name='remoteapp', - name='system_user', - ), - ] diff --git a/apps/applications/migrations/0003_auto_20191210_1659.py b/apps/applications/migrations/0003_auto_20191210_1659.py deleted file mode 100644 index fc3e4cdf5..000000000 --- a/apps/applications/migrations/0003_auto_20191210_1659.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.11 on 2019-12-10 08:59 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0002_remove_remoteapp_system_user'), - ] - - operations = [ - migrations.AlterField( - model_name='remoteapp', - name='type', - field=models.CharField(choices=[('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom')], default='chrome', max_length=128, verbose_name='App type'), - ), - ] diff --git a/apps/applications/migrations/0004_auto_20191218_1705.py b/apps/applications/migrations/0004_auto_20191218_1705.py deleted file mode 100644 index f22d2e290..000000000 --- a/apps/applications/migrations/0004_auto_20191218_1705.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 2.1.11 on 2019-12-18 09:05 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0003_auto_20191210_1659'), - ] - - operations = [ - migrations.CreateModel( - name='DatabaseApp', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('type', models.CharField(choices=[('mysql', 'MySQL')], default='mysql', max_length=128, verbose_name='Type')), - ('host', models.CharField(db_index=True, max_length=128, verbose_name='Host')), - ('port', models.IntegerField(default=3306, verbose_name='Port')), - ('database', models.CharField(blank=True, db_index=True, max_length=128, null=True, verbose_name='Database')), - ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), - ], - options={ - 'verbose_name': 'DatabaseApp', - 'ordering': ('name',), - }, - ), - migrations.AlterUniqueTogether( - name='databaseapp', - unique_together={('org_id', 'name')}, - ), - ] diff --git a/apps/applications/migrations/0005_k8sapp.py b/apps/applications/migrations/0005_k8sapp.py deleted file mode 100644 index 3f6964a88..000000000 --- a/apps/applications/migrations/0005_k8sapp.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-07 07:13 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0004_auto_20191218_1705'), - ] - - operations = [ - migrations.CreateModel( - name='K8sApp', - fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('type', models.CharField(choices=[('k8s', 'Kubernetes')], default='k8s', max_length=128, verbose_name='Type')), - ('cluster', models.CharField(max_length=1024, verbose_name='Cluster')), - ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), - ], - options={ - 'verbose_name': 'KubernetesApp', - 'ordering': ('name',), - 'unique_together': {('org_id', 'name')}, - }, - ), - ] diff --git a/apps/applications/migrations/0006_application.py b/apps/applications/migrations/0006_application.py deleted file mode 100644 index 423e9468a..000000000 --- a/apps/applications/migrations/0006_application.py +++ /dev/null @@ -1,139 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-19 12:01 - -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -CATEGORY_DB_LIST = ['mysql', 'oracle', 'postgresql', 'mariadb'] -CATEGORY_REMOTE_LIST = ['chrome', 'mysql_workbench', 'vmware_client', 'custom'] -CATEGORY_CLOUD_LIST = ['k8s'] - -CATEGORY_DB = 'db' -CATEGORY_REMOTE = 'remote_app' -CATEGORY_CLOUD = 'cloud' -CATEGORY_LIST = [CATEGORY_DB, CATEGORY_REMOTE, CATEGORY_CLOUD] - - -def get_application_category(old_app): - _type = old_app.type - if _type in CATEGORY_DB_LIST: - category = CATEGORY_DB - elif _type in CATEGORY_REMOTE_LIST: - category = CATEGORY_REMOTE - elif _type in CATEGORY_CLOUD_LIST: - category = CATEGORY_CLOUD - else: - category = None - return category - - -def common_to_application_json(old_app): - category = get_application_category(old_app) - date_updated = old_app.date_updated if hasattr(old_app, 'date_updated') else old_app.date_created - return { - 'id': old_app.id, - 'name': old_app.name, - 'type': old_app.type, - 'category': category, - 'comment': old_app.comment, - 'created_by': old_app.created_by, - 'date_created': old_app.date_created, - 'date_updated': date_updated, - 'org_id': old_app.org_id - } - - -def db_to_application_json(database): - app_json = common_to_application_json(database) - app_json.update({ - 'attrs': { - 'host': database.host, - 'port': database.port, - 'database': database.database - } - }) - return app_json - - -def remote_to_application_json(remote): - app_json = common_to_application_json(remote) - attrs = { - 'asset': str(remote.asset.id), - 'path': remote.path, - } - attrs.update(remote.params) - app_json.update({ - 'attrs': attrs - }) - return app_json - - -def k8s_to_application_json(k8s): - app_json = common_to_application_json(k8s) - app_json.update({ - 'attrs': { - 'cluster': k8s.cluster - } - }) - return app_json - - -def migrate_and_integrate_applications(apps, schema_editor): - db_alias = schema_editor.connection.alias - - database_app_model = apps.get_model("applications", "DatabaseApp") - remote_app_model = apps.get_model("applications", "RemoteApp") - k8s_app_model = apps.get_model("applications", "K8sApp") - - database_apps = database_app_model.objects.using(db_alias).all() - remote_apps = remote_app_model.objects.using(db_alias).all() - k8s_apps = k8s_app_model.objects.using(db_alias).all() - - database_applications = [db_to_application_json(db_app) for db_app in database_apps] - remote_applications = [remote_to_application_json(remote_app) for remote_app in remote_apps] - k8s_applications = [k8s_to_application_json(k8s_app) for k8s_app in k8s_apps] - - applications_json = database_applications + remote_applications + k8s_applications - application_model = apps.get_model("applications", "Application") - applications = [ - application_model(**application_json) - for application_json in applications_json - if application_json['category'] in CATEGORY_LIST - ] - for application in applications: - if application_model.objects.using(db_alias).filter(name=application.name).exists(): - application.name = '{}-{}'.format(application.name, application.type) - application.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0057_fill_node_value_assets_amount_and_parent_key'), - ('applications', '0005_k8sapp'), - ] - - operations = [ - migrations.CreateModel( - name='Application', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('category', models.CharField(choices=[('db', 'Database'), ('remote_app', 'Remote app'), ('cloud', 'Cloud')], max_length=16, verbose_name='Category')), - ('type', models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type')), - ('attrs', models.JSONField(default=dict)), - ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), - ('domain', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='applications', to='assets.Domain', verbose_name='Domain')), - ], - options={ - 'ordering': ('name',), - 'unique_together': {('org_id', 'name')}, - }, - ), - migrations.RunPython(migrate_and_integrate_applications), - ] diff --git a/apps/applications/migrations/0007_auto_20201119_1110.py b/apps/applications/migrations/0007_auto_20201119_1110.py deleted file mode 100644 index e206f8404..000000000 --- a/apps/applications/migrations/0007_auto_20201119_1110.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2020-11-19 03:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0006_application'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='attrs', - field=models.JSONField(), - ), - ] diff --git a/apps/applications/migrations/0008_auto_20210104_0435.py b/apps/applications/migrations/0008_auto_20210104_0435.py deleted file mode 100644 index 2942ecf6e..000000000 --- a/apps/applications/migrations/0008_auto_20210104_0435.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.1 on 2021-01-03 20:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0017_auto_20210104_0435'), - ('applications', '0007_auto_20201119_1110'), - ] - - operations = [ - migrations.DeleteModel( - name='DatabaseApp', - ), - migrations.DeleteModel( - name='K8sApp', - ), - migrations.AlterField( - model_name='application', - name='attrs', - field=models.JSONField(default=dict, verbose_name='Attrs'), - ), - migrations.DeleteModel( - name='RemoteApp', - ), - ] diff --git a/apps/applications/migrations/0009_applicationuser.py b/apps/applications/migrations/0009_applicationuser.py deleted file mode 100644 index 7b3368ef9..000000000 --- a/apps/applications/migrations/0009_applicationuser.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-23 09:48 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0070_auto_20210426_1515'), - ('applications', '0008_auto_20210104_0435'), - ] - - operations = [ - migrations.CreateModel( - name='ApplicationUser', - fields=[ - ], - options={ - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.systemuser',), - ), - ] diff --git a/apps/applications/migrations/0010_appaccount_historicalappaccount.py b/apps/applications/migrations/0010_appaccount_historicalappaccount.py deleted file mode 100644 index 515754f32..000000000 --- a/apps/applications/migrations/0010_appaccount_historicalappaccount.py +++ /dev/null @@ -1,96 +0,0 @@ -# Generated by Django 3.1.12 on 2021-08-26 09:07 - -import uuid - -import django.core.validators -import django.db.models.deletion -import simple_history.models -from django.conf import settings -from django.db import migrations, models - -import common.db.fields - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0076_delete_assetuser'), - ('applications', '0009_applicationuser'), - ] - - operations = [ - migrations.CreateModel( - name='HistoricalAccount', - fields=[ - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(db_index=True, default=uuid.uuid4)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('username', models.CharField(blank=True, db_index=True, max_length=128, validators=[ - django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], - verbose_name='Username')), - ('password', - common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('private_key', - common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')), - ('public_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('date_created', models.DateTimeField(blank=True, editable=False, verbose_name='Date created')), - ('date_updated', models.DateTimeField(blank=True, editable=False, verbose_name='Date updated')), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('version', models.IntegerField(default=1, verbose_name='Version')), - ('history_id', models.AutoField(primary_key=True, serialize=False)), - ('history_date', models.DateTimeField()), - ('history_change_reason', models.CharField(max_length=100, null=True)), - ('history_type', - models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), - ('app', models.ForeignKey(blank=True, db_constraint=False, null=True, - on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', - to='applications.application', verbose_name='Database')), - ('history_user', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', - to=settings.AUTH_USER_MODEL)), - ('systemuser', models.ForeignKey(blank=True, db_constraint=False, null=True, - on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', - to='assets.systemuser', verbose_name='System user')), - ], - options={ - 'verbose_name': 'historical Account', - 'ordering': ('-history_date', '-history_id'), - 'get_latest_by': 'history_date', - }, - bases=(simple_history.models.HistoricalChanges, models.Model), - ), - migrations.CreateModel( - name='Account', - fields=[ - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('username', models.CharField(blank=True, db_index=True, max_length=128, validators=[ - django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], - verbose_name='Username')), - ('password', - common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('private_key', - common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')), - ('public_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('version', models.IntegerField(default=1, verbose_name='Version')), - ('app', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, - to='applications.application', verbose_name='Database')), - ('systemuser', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.systemuser', - verbose_name='System user')), - ], - options={ - 'verbose_name': 'Account', - 'unique_together': {('username', 'app', 'systemuser')}, - }, - bases=(models.Model,), - ), - ] diff --git a/apps/applications/migrations/0011_auto_20210826_1759.py b/apps/applications/migrations/0011_auto_20210826_1759.py deleted file mode 100644 index 937102c07..000000000 --- a/apps/applications/migrations/0011_auto_20210826_1759.py +++ /dev/null @@ -1,40 +0,0 @@ -# Generated by Django 3.1.12 on 2021-08-26 09:59 - -from django.db import migrations, transaction -from django.db.models import F - - -def migrate_app_account(apps, schema_editor): - db_alias = schema_editor.connection.alias - app_perm_model = apps.get_model("perms", "ApplicationPermission") - app_account_model = apps.get_model("applications", 'Account') - - queryset = app_perm_model.objects \ - .exclude(system_users__isnull=True) \ - .exclude(applications__isnull=True) \ - .annotate(systemuser=F('system_users')) \ - .annotate(app=F('applications')) \ - .values('app', 'systemuser', 'org_id') - - accounts = [] - for p in queryset: - if not p['app']: - continue - account = app_account_model( - app_id=p['app'], systemuser_id=p['systemuser'], - version=1, org_id=p['org_id'] - ) - accounts.append(account) - - app_account_model.objects.using(db_alias).bulk_create(accounts, ignore_conflicts=True) - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0010_appaccount_historicalappaccount'), - ] - - operations = [ - migrations.RunPython(migrate_app_account) - ] diff --git a/apps/applications/migrations/0012_auto_20211014_2209.py b/apps/applications/migrations/0012_auto_20211014_2209.py deleted file mode 100644 index 3375f7399..000000000 --- a/apps/applications/migrations/0012_auto_20211014_2209.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.13 on 2021-10-14 14:09 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0011_auto_20210826_1759'), - ] - - operations = [ - migrations.AlterField( - model_name='account', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='historicalaccount', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - ] diff --git a/apps/applications/migrations/0013_auto_20211026_1711.py b/apps/applications/migrations/0013_auto_20211026_1711.py deleted file mode 100644 index 28d80cdbc..000000000 --- a/apps/applications/migrations/0013_auto_20211026_1711.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.13 on 2021-10-26 09:11 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0012_auto_20211014_2209'), - ] - - operations = [ - migrations.AlterModelOptions( - name='application', - options={'ordering': ('name',), 'verbose_name': 'Application'}, - ), - ] diff --git a/apps/applications/migrations/0014_auto_20211105_1605.py b/apps/applications/migrations/0014_auto_20211105_1605.py deleted file mode 100644 index ab0063c3c..000000000 --- a/apps/applications/migrations/0014_auto_20211105_1605.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.12 on 2021-11-05 08:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0013_auto_20211026_1711'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0015_auto_20220112_2035.py b/apps/applications/migrations/0015_auto_20220112_2035.py deleted file mode 100644 index 3f91878df..000000000 --- a/apps/applications/migrations/0015_auto_20220112_2035.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-01-12 12:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0014_auto_20211105_1605'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('redis', 'Redis'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0016_auto_20220118_1455.py b/apps/applications/migrations/0016_auto_20220118_1455.py deleted file mode 100644 index edb97bade..000000000 --- a/apps/applications/migrations/0016_auto_20220118_1455.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.1.13 on 2022-01-18 06:55 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0015_auto_20220112_2035'), - ] - - operations = [ - migrations.AlterField( - model_name='account', - name='app', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='applications.application', verbose_name='Application'), - ), - migrations.AlterField( - model_name='historicalaccount', - name='app', - field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='applications.application', verbose_name='Application'), - ), - ] diff --git a/apps/applications/migrations/0017_auto_20220217_2135.py b/apps/applications/migrations/0017_auto_20220217_2135.py deleted file mode 100644 index fd6bbeaa8..000000000 --- a/apps/applications/migrations/0017_auto_20220217_2135.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-17 13:35 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0016_auto_20220118_1455'), - ] - - operations = [ - migrations.AlterModelOptions( - name='account', - options={'permissions': [('view_applicationaccountsecret', 'Can view application account secret'), ('change_appplicationaccountsecret', 'Can change application account secret')], 'verbose_name': 'Application account'}, - ), - migrations.AlterModelOptions( - name='applicationuser', - options={'verbose_name': 'Application user'}, - ), - migrations.AlterModelOptions( - name='historicalaccount', - options={'get_latest_by': 'history_date', 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Application account'}, - ), - ] diff --git a/apps/applications/migrations/0018_auto_20220223_1539.py b/apps/applications/migrations/0018_auto_20220223_1539.py deleted file mode 100644 index 637d8cb86..000000000 --- a/apps/applications/migrations/0018_auto_20220223_1539.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-23 07:39 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0017_auto_20220217_2135'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0019_auto_20220310_1853.py b/apps/applications/migrations/0019_auto_20220310_1853.py deleted file mode 100644 index 42a5683a0..000000000 --- a/apps/applications/migrations/0019_auto_20220310_1853.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-10 10:53 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0018_auto_20220223_1539'), - ] - - operations = [ - migrations.AlterModelOptions( - name='application', - options={'ordering': ('name',), 'permissions': [('match_application', 'Can match application')], 'verbose_name': 'Application'}, - ), - ] diff --git a/apps/applications/migrations/0020_auto_20220316_2028.py b/apps/applications/migrations/0020_auto_20220316_2028.py deleted file mode 100644 index 3eeedf2d6..000000000 --- a/apps/applications/migrations/0020_auto_20220316_2028.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-16 12:28 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0019_auto_20220310_1853'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0021_auto_20220629_1826.py b/apps/applications/migrations/0021_auto_20220629_1826.py deleted file mode 100644 index b74977b7d..000000000 --- a/apps/applications/migrations/0021_auto_20220629_1826.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.1.14 on 2022-06-29 10:26 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0020_auto_20220316_2028'), - ] - - operations = [ - migrations.AlterModelOptions( - name='historicalaccount', - options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical Application account', 'verbose_name_plural': 'historical Application accounts'}, - ), - migrations.AlterField( - model_name='historicalaccount', - name='history_date', - field=models.DateTimeField(db_index=True), - ), - ] diff --git a/apps/applications/migrations/0022_auto_20220714_1046.py b/apps/applications/migrations/0022_auto_20220714_1046.py deleted file mode 100644 index f7475a8c3..000000000 --- a/apps/applications/migrations/0022_auto_20220714_1046.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.2.12 on 2022-07-14 02:46 - -from django.db import migrations - - -def migrate_db_oracle_version_to_attrs(apps, schema_editor): - db_alias = schema_editor.connection.alias - model = apps.get_model("applications", "Application") - oracles = list(model.objects.using(db_alias).filter(type='oracle')) - for o in oracles: - o.attrs['version'] = '12c' - model.objects.using(db_alias).bulk_update(oracles, ['attrs']) - - -class Migration(migrations.Migration): - dependencies = [ - ('applications', '0021_auto_20220629_1826'), - ] - - operations = [ - migrations.RunPython(migrate_db_oracle_version_to_attrs) - ] diff --git a/apps/applications/migrations/0023_auto_20220715_1556.py b/apps/applications/migrations/0023_auto_20220715_1556.py deleted file mode 100644 index bc6e20770..000000000 --- a/apps/applications/migrations/0023_auto_20220715_1556.py +++ /dev/null @@ -1,47 +0,0 @@ -# Generated by Django 3.1.14 on 2022-07-15 07:56 -import time - -from django.db import migrations - - -def migrate_account_dirty_data(apps, schema_editor): - db_alias = schema_editor.connection.alias - account_model = apps.get_model('applications', 'Account') - - count = 0 - bulk_size = 1000 - - while True: - accounts = account_model.objects.using(db_alias) \ - .filter(org_id='')[count:count + bulk_size] - - if not accounts: - break - - accounts = list(accounts) - start = time.time() - for i in accounts: - if i.app: - org_id = i.app.org_id - elif i.systemuser: - org_id = i.systemuser.org_id - else: - org_id = '' - if org_id: - i.org_id = org_id - - account_model.objects.bulk_update(accounts, ['org_id', ]) - print("Update account org is empty: {}-{} using: {:.2f}s".format( - count, count + len(accounts), time.time() - start - )) - count += len(accounts) - - -class Migration(migrations.Migration): - dependencies = [ - ('applications', '0022_auto_20220714_1046'), - ] - - operations = [ - migrations.RunPython(migrate_account_dirty_data), - ] diff --git a/apps/applications/migrations/0024_alter_application_type.py b/apps/applications/migrations/0024_alter_application_type.py deleted file mode 100644 index 4f26e0905..000000000 --- a/apps/applications/migrations/0024_alter_application_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.14 on 2022-11-04 07:06 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0023_auto_20220715_1556'), - ] - - operations = [ - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('clickhouse', 'ClickHouse'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0025_auto_20220817_1346.py b/apps/applications/migrations/0025_auto_20220817_1346.py deleted file mode 100644 index a1a7da6ea..000000000 --- a/apps/applications/migrations/0025_auto_20220817_1346.py +++ /dev/null @@ -1,60 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-17 05:46 - -from django.db import migrations, models - - -def migrate_db_oracle_version_to_attrs(apps, schema_editor): - db_alias = schema_editor.connection.alias - model = apps.get_model("applications", "Application") - oracles = list(model.objects.using(db_alias).filter(type='oracle')) - for o in oracles: - o.attrs['version'] = '12c' - model.objects.using(db_alias).bulk_update(oracles, ['attrs']) - - -class Migration(migrations.Migration): - dependencies = [ - ('applications', '0024_alter_application_type'), - ] - - operations = [ - migrations.RunPython(migrate_db_oracle_version_to_attrs), - migrations.AlterUniqueTogether( - name='account', - unique_together=None, - ), - migrations.RemoveField( - model_name='account', - name='app', - ), - migrations.RemoveField( - model_name='account', - name='systemuser', - ), - migrations.RemoveField( - model_name='application', - name='domain', - ), - migrations.RemoveField( - model_name='historicalaccount', - name='app', - ), - migrations.RemoveField( - model_name='historicalaccount', - name='history_user', - ), - migrations.RemoveField( - model_name='historicalaccount', - name='systemuser', - ), - migrations.AlterField( - model_name='application', - name='category', - field=models.CharField(max_length=16, verbose_name='Category'), - ), - migrations.AlterField( - model_name='application', - name='type', - field=models.CharField(max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/applications/migrations/0026_auto_20220817_1716.py b/apps/applications/migrations/0026_auto_20220817_1716.py deleted file mode 100644 index bb9df0808..000000000 --- a/apps/applications/migrations/0026_auto_20220817_1716.py +++ /dev/null @@ -1,60 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-17 09:16 -import time - -from django.db import migrations - - -def migrate_account_dirty_data(apps, schema_editor): - db_alias = schema_editor.connection.alias - account_model = apps.get_model('applications', 'Account') - - count = 0 - bulk_size = 1000 - - while True: - accounts = account_model.objects.using(db_alias) \ - .filter(org_id='')[count:count + bulk_size] - - if not accounts: - break - - accounts = list(accounts) - start = time.time() - for i in accounts: - if i.app: - org_id = i.app.org_id - elif i.systemuser: - org_id = i.systemuser.org_id - else: - org_id = '' - if org_id: - i.org_id = org_id - - account_model.objects.bulk_update(accounts, ['org_id', ]) - print("Update account org is empty: {}-{} using: {:.2f}s".format( - count, count + len(accounts), time.time() - start - )) - count += len(accounts) - - -class Migration(migrations.Migration): - dependencies = [ - ('applications', '0025_auto_20220817_1346'), - ('perms', '0031_auto_20220816_1600'), - ('ops', '0022_auto_20220817_1346'), - ('assets', '0100_auto_20220711_1413'), - ('tickets', '0020_auto_20220817_1346'), - ] - - operations = [ - migrations.RunPython(migrate_account_dirty_data), - migrations.DeleteModel( - name='Account', - ), - migrations.DeleteModel( - name='HistoricalAccount', - ), - migrations.DeleteModel( - name='ApplicationUser', - ), - ] diff --git a/apps/applications/migrations/0027_auto_20221220_1956.py b/apps/applications/migrations/0027_auto_20221220_1956.py deleted file mode 100644 index a72162974..000000000 --- a/apps/applications/migrations/0027_auto_20221220_1956.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0026_auto_20220817_1716'), - ] - - operations = [ - migrations.AddField( - model_name='application', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='application', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='application', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - ] diff --git a/apps/applications/migrations/__init__.py b/apps/applications/migrations/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/applications/models.py b/apps/applications/models.py deleted file mode 100644 index c13ddc092..000000000 --- a/apps/applications/models.py +++ /dev/null @@ -1,24 +0,0 @@ -from django.db import models -from django.utils.translation import gettext_lazy as _ - -from common.db.models import JMSBaseModel -from orgs.mixins.models import OrgModelMixin - - -class Application(JMSBaseModel, OrgModelMixin): - name = models.CharField(max_length=128, verbose_name=_('Name')) - category = models.CharField( - max_length=16, verbose_name=_('Category') - ) - type = models.CharField( - max_length=16, verbose_name=_('Type') - ) - attrs = models.JSONField(default=dict, verbose_name=_('Attrs')) - - class Meta: - verbose_name = _('Application') - unique_together = [('org_id', 'name')] - ordering = ('name',) - permissions = [ - ('match_application', _('Can match application')), - ] diff --git a/apps/applications/signal_handlers.py b/apps/applications/signal_handlers.py deleted file mode 100644 index 4aa11c79b..000000000 --- a/apps/applications/signal_handlers.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -# \ No newline at end of file diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py index 94a2c262c..b03f22d12 100644 --- a/apps/assets/const/types.py +++ b/apps/assets/const/types.py @@ -334,11 +334,13 @@ class AllTypes(ChoicesMixin): return data @classmethod - def create_or_update_by_platform_data(cls, platform_data, platform_cls=None): + def create_or_update_by_platform_data(cls, platform_data, platform_cls=None, automation_cls=None): # 不直接用 Platform 是因为可能在 migrations 中使用 - from assets.models import Platform + from assets.models import Platform, PlatformAutomation if platform_cls is None: platform_cls = Platform + if automation_cls is None: + automation_cls = PlatformAutomation automation_data = platform_data.pop('automation', {}) protocols_data = platform_data.pop('protocols', []) @@ -347,12 +349,18 @@ class AllTypes(ChoicesMixin): platform, created = platform_cls.objects.update_or_create( defaults=platform_data, name=name ) - if not platform.automation: - automation = platform_cls.automation.field.related_model.objects.create() + + try: + automation = platform.automation + except: + automation = None + + if not automation: + automation = automation_cls.objects.create() platform.automation = automation platform.save() else: - automation = platform.automation + automation = automation for k, v in automation_data.items(): setattr(automation, k, v) automation.save() diff --git a/apps/assets/migrations/0001_initial.py b/apps/assets/migrations/0001_initial.py index 03c945c57..1ac461075 100644 --- a/apps/assets/migrations/0001_initial.py +++ b/apps/assets/migrations/0001_initial.py @@ -1,21 +1,13 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2017-12-21 16:06 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import assets.models.utils +import assets.models.asset.common +import assets.models.node +import common.db.fields from django.db import migrations, models import django.db.models.deletion import uuid -def add_default_group(apps, schema_editor): - group_model = apps.get_model("assets", "AssetGroup") - db_alias = schema_editor.connection.alias - group_model.objects.using(db_alias).create( - name="Default" - ) - - class Migration(migrations.Migration): initial = True @@ -24,136 +16,306 @@ class Migration(migrations.Migration): ] operations = [ - migrations.CreateModel( - name='AdminUser', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('username', models.CharField(max_length=16, verbose_name='Username')), - ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), - ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(max_length=32, null=True, verbose_name='Created by')), - ('become', models.BooleanField(default=True)), - ('become_method', models.CharField(choices=[('sudo', 'sudo'), ('su', 'su')], default='sudo', max_length=4)), - ('become_user', models.CharField(default='root', max_length=64)), - ('_become_pass', models.CharField(default='', max_length=128)), - ], - options={ - 'ordering': ['name'], - }, - ), migrations.CreateModel( name='Asset', 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('ip', models.GenericIPAddressField(db_index=True, verbose_name='IP')), - ('hostname', models.CharField(max_length=128, unique=True, verbose_name='Hostname')), - ('port', models.IntegerField(default=22, verbose_name='Port')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('connectivity', models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity')), + ('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('address', models.CharField(db_index=True, max_length=767, verbose_name='Address')), ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('type', models.CharField(blank=True, choices=[('Server', 'Server'), ('VM', 'VM'), ('Switch', 'Switch'), ('Router', 'Router'), ('Firewall', 'Firewall'), ('Storage', 'Storage')], default='Server', max_length=16, null=True, verbose_name='Asset type')), - ('env', models.CharField(blank=True, choices=[('Prod', 'Production'), ('Dev', 'Development'), ('Test', 'Testing')], default='Prod', max_length=8, null=True, verbose_name='Asset environment')), - ('status', models.CharField(blank=True, choices=[('In use', 'In use'), ('Out of use', 'Out of use')], default='In use', max_length=12, null=True, verbose_name='Asset status')), - ('public_ip', models.GenericIPAddressField(blank=True, null=True, verbose_name='Public IP')), - ('remote_card_ip', models.CharField(blank=True, max_length=16, null=True, verbose_name='Remote control card IP')), - ('cabinet_no', models.CharField(blank=True, max_length=32, null=True, verbose_name='Cabinet number')), - ('cabinet_pos', models.IntegerField(blank=True, null=True, verbose_name='Cabinet position')), - ('number', models.CharField(blank=True, max_length=32, null=True, verbose_name='Asset number')), - ('vendor', models.CharField(blank=True, max_length=64, null=True, verbose_name='Vendor')), - ('model', models.CharField(blank=True, max_length=54, null=True, verbose_name='Model')), - ('sn', models.CharField(blank=True, max_length=128, null=True, verbose_name='Serial number')), - ('cpu_model', models.CharField(blank=True, max_length=64, null=True, verbose_name='CPU model')), - ('cpu_count', models.IntegerField(null=True, verbose_name='CPU count')), - ('cpu_cores', models.IntegerField(null=True, verbose_name='CPU cores')), - ('memory', models.CharField(blank=True, max_length=64, null=True, verbose_name='Memory')), - ('disk_total', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Disk total')), - ('disk_info', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Disk info')), - ('platform', models.CharField(blank=True, max_length=128, null=True, verbose_name='Platform')), - ('os', models.CharField(blank=True, max_length=128, null=True, verbose_name='OS')), - ('os_version', models.CharField(blank=True, max_length=16, null=True, verbose_name='OS version')), - ('os_arch', models.CharField(blank=True, max_length=16, null=True, verbose_name='OS arch')), - ('hostname_raw', models.CharField(blank=True, max_length=128, null=True, verbose_name='Hostname raw')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), - ('admin_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.AdminUser', verbose_name='Admin user')), - ], - ), - migrations.CreateModel( - name='AssetGroup', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=64, unique=True, verbose_name='Name')), - ('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), + ('gathered_info', models.JSONField(blank=True, default=dict, verbose_name='Gathered info')), + ('custom_info', models.JSONField(default=dict, verbose_name='Custom info')), ], options={ - 'ordering': ['name'], + 'verbose_name': 'Asset', + 'ordering': [], + 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('match_asset', 'Can match asset'), ('change_assetnodes', 'Can change asset nodes')], + }, + bases=(assets.models.asset.common.NodesRelationMixin, assets.models.asset.common.JSONFilterMixin, models.Model), + ), + migrations.CreateModel( + name='AutomationExecution', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), + ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), + ('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')), + ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), + ('snapshot', common.db.fields.EncryptJsonDictTextField(blank=True, default=dict, null=True, verbose_name='Automation snapshot')), + ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')), + ], + options={ + 'verbose_name': 'Automation task execution', + 'ordering': ('-date_start',), }, ), migrations.CreateModel( - name='Cluster', + name='BaseAutomation', 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('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')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')), + ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')), + ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')), + ('accounts', models.JSONField(default=list, verbose_name='Accounts')), + ('type', models.CharField(max_length=16, verbose_name='Type')), + ('is_active', models.BooleanField(default=True, verbose_name='Is active')), + ('params', models.JSONField(default=dict, verbose_name='Parameters')), + ], + options={ + 'verbose_name': 'Automation task', + }, + ), + migrations.CreateModel( + name='Domain', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('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')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ], + options={ + 'verbose_name': 'Zone', + 'ordering': ('name',), + }, + ), + migrations.CreateModel( + name='Node', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('key', models.CharField(max_length=64, unique=True, verbose_name='Key')), + ('value', models.CharField(max_length=128, verbose_name='Value')), + ('full_value', models.CharField(default='', max_length=4096, verbose_name='Full value')), + ('child_mark', models.IntegerField(default=0)), + ('date_create', models.DateTimeField(auto_now_add=True)), + ('parent_key', models.CharField(db_index=True, default='', max_length=64, verbose_name='Parent key')), + ('assets_amount', models.IntegerField(default=0)), + ], + options={ + 'verbose_name': 'Node', + 'ordering': ['parent_key', 'value'], + 'permissions': [('match_node', 'Can match node')], + }, + bases=(models.Model, assets.models.node.SomeNodesMixin, assets.models.node.FamilyMixin, assets.models.node.NodeAssetsMixin), + ), + migrations.CreateModel( + name='Platform', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('name', models.SlugField(allow_unicode=True, unique=True, verbose_name='Name')), + ('category', models.CharField(default='host', max_length=32, verbose_name='Category')), + ('type', models.CharField(default='linux', max_length=32, verbose_name='Type')), + ('meta', common.db.fields.JsonDictTextField(blank=True, null=True, verbose_name='Meta')), + ('internal', models.BooleanField(default=False, verbose_name='Internal')), + ('charset', models.CharField(choices=[('utf-8', 'UTF-8'), ('gbk', 'GBK')], default='utf-8', max_length=8, verbose_name='Charset')), + ('domain_enabled', models.BooleanField(default=True, verbose_name='Domain enabled')), + ('su_enabled', models.BooleanField(default=False, verbose_name='Su enabled')), + ('su_method', models.CharField(blank=True, max_length=32, null=True, verbose_name='Su method')), + ('custom_fields', models.JSONField(default=list, null=True, verbose_name='Custom fields')), + ], + options={ + 'verbose_name': 'Platform', + }, + ), + migrations.CreateModel( + name='Cloud', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ], + options={ + 'verbose_name': 'Cloud', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Custom', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ], + options={ + 'verbose_name': 'Custom asset', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Database', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ('db_name', models.CharField(blank=True, max_length=1024, verbose_name='Database')), + ('use_ssl', models.BooleanField(default=False, verbose_name='Use SSL')), + ('ca_cert', common.db.fields.EncryptTextField(blank=True, verbose_name='CA cert')), + ('client_cert', common.db.fields.EncryptTextField(blank=True, verbose_name='Client cert')), + ('client_key', common.db.fields.EncryptTextField(blank=True, verbose_name='Client key')), + ('allow_invalid_cert', models.BooleanField(default=False, verbose_name='Allow invalid cert')), + ], + options={ + 'verbose_name': 'Database', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Device', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ], + options={ + 'verbose_name': 'Device', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='GPT', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ('proxy', models.CharField(blank=True, default='', max_length=128, verbose_name='Proxy')), + ], + options={ + 'verbose_name': 'Web', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Host', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ], + options={ + 'verbose_name': 'Host', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Web', + fields=[ + ('asset_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.asset')), + ('autofill', models.CharField(choices=[('no', 'Disabled'), ('basic', 'Basic'), ('script', 'Script')], default='basic', max_length=16, verbose_name='Autofill')), + ('username_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Username selector')), + ('password_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Password selector')), + ('submit_selector', models.CharField(blank=True, default='', max_length=128, verbose_name='Submit selector')), + ('script', models.JSONField(blank=True, default=list, verbose_name='Script')), + ], + options={ + 'verbose_name': 'Web', + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='Protocol', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=32, verbose_name='Name')), - ('bandwidth', models.CharField(blank=True, max_length=32, verbose_name='Bandwidth')), - ('contact', models.CharField(blank=True, max_length=128, verbose_name='Contact')), - ('phone', models.CharField(blank=True, max_length=32, verbose_name='Phone')), - ('address', models.CharField(blank=True, max_length=128, verbose_name='Address')), - ('intranet', models.TextField(blank=True, verbose_name='Intranet')), - ('extranet', models.TextField(blank=True, verbose_name='Extranet')), + ('port', models.IntegerField(verbose_name='Port')), + ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='protocols', to='assets.asset', verbose_name='Asset')), + ], + ), + migrations.CreateModel( + name='PlatformProtocol', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=32, verbose_name='Name')), + ('port', models.IntegerField(verbose_name='Port')), + ('primary', models.BooleanField(default=False, verbose_name='Primary')), + ('required', models.BooleanField(default=False, verbose_name='Required')), + ('default', models.BooleanField(default=False, verbose_name='Default')), + ('public', models.BooleanField(default=True, verbose_name='Public')), + ('setting', models.JSONField(default=dict, verbose_name='Setting')), + ('platform', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='protocols', to='assets.platform')), + ], + ), + migrations.CreateModel( + name='PlatformAutomation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('ansible_enabled', models.BooleanField(default=False, verbose_name='Enabled')), + ('ansible_config', models.JSONField(default=dict, verbose_name='Ansible config')), + ('ping_enabled', models.BooleanField(default=False, verbose_name='Ping enabled')), + ('ping_method', models.CharField(blank=True, max_length=32, null=True, verbose_name='Ping method')), + ('ping_params', models.JSONField(default=dict, verbose_name='Ping params')), + ('gather_facts_enabled', models.BooleanField(default=False, verbose_name='Gather facts enabled')), + ('gather_facts_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method')), + ('gather_facts_params', models.JSONField(default=dict, verbose_name='Gather facts params')), + ('change_secret_enabled', models.BooleanField(default=False, verbose_name='Change secret enabled')), + ('change_secret_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Change secret method')), + ('change_secret_params', models.JSONField(default=dict, verbose_name='Change secret params')), + ('push_account_enabled', models.BooleanField(default=False, verbose_name='Push account enabled')), + ('push_account_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Push account method')), + ('push_account_params', models.JSONField(default=dict, verbose_name='Push account params')), + ('verify_account_enabled', models.BooleanField(default=False, verbose_name='Verify account enabled')), + ('verify_account_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Verify account method')), + ('verify_account_params', models.JSONField(default=dict, verbose_name='Verify account params')), + ('gather_accounts_enabled', models.BooleanField(default=False, verbose_name='Gather facts enabled')), + ('gather_accounts_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method')), + ('gather_accounts_params', models.JSONField(default=dict, verbose_name='Gather facts params')), + ('remove_account_enabled', models.BooleanField(default=False, verbose_name='Remove account enabled')), + ('remove_account_method', models.TextField(blank=True, max_length=32, null=True, verbose_name='Remove account method')), + ('remove_account_params', models.JSONField(default=dict, verbose_name='Remove account params')), + ('platform', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='automation', to='assets.platform')), + ], + ), + migrations.CreateModel( + name='Label', + 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')), - ('operator', models.CharField(blank=True, max_length=32, verbose_name='Operator')), - ('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('admin_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.AdminUser', verbose_name='Admin user')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('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')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('value', models.CharField(max_length=128, verbose_name='Value')), + ('category', models.CharField(choices=[('S', 'System'), ('U', 'User')], default='U', max_length=128, verbose_name='Category')), + ('is_active', models.BooleanField(default=True, verbose_name='Is active')), ], options={ - 'ordering': ['name'], + 'verbose_name': 'Label', + 'db_table': 'assets_label', + 'unique_together': {('name', 'value', 'org_id')}, }, ), migrations.CreateModel( - name='SystemUser', + name='FavoriteAsset', 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('username', models.CharField(max_length=16, verbose_name='Username')), - ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), - ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(max_length=32, null=True, verbose_name='Created by')), - ('priority', models.IntegerField(default=10, verbose_name='Priority')), - ('protocol', models.CharField(choices=[('ssh', 'ssh')], default='ssh', max_length=16, verbose_name='Protocol')), - ('auto_push', models.BooleanField(default=True, verbose_name='Auto push')), - ('sudo', models.TextField(default='/sbin/ifconfig', verbose_name='Sudo')), - ('shell', models.CharField(default='/bin/bash', max_length=64, verbose_name='Shell')), - ('cluster', models.ManyToManyField(blank=True, to='assets.Cluster', verbose_name='Cluster')), + ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.asset')), ], options={ - 'ordering': ['name'], + 'verbose_name': 'Favorite asset', }, ), - migrations.AddField( - model_name='asset', - name='cluster', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assets', to='assets.Cluster', verbose_name='Cluster'), - ), - migrations.AddField( - model_name='asset', - name='groups', - field=models.ManyToManyField(blank=True, related_name='assets', to='assets.AssetGroup', verbose_name='Asset groups'), - ), - migrations.AlterUniqueTogether( - name='asset', - unique_together=set([('ip', 'port')]), - ), - - migrations.RunPython(add_default_group), ] diff --git a/apps/assets/migrations/0002_auto_20180105_1807.py b/apps/assets/migrations/0002_auto_20180105_1807.py index bf1f022ac..5f526f661 100644 --- a/apps/assets/migrations/0002_auto_20180105_1807.py +++ b/apps/assets/migrations/0002_auto_20180105_1807.py @@ -1,35 +1,115 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-05 10:07 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 -from django.db import migrations +import json +import assets.models.asset.common +from django.db.models import F, Q +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): + initial = True dependencies = [ ('assets', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.AlterModelOptions( - name='adminuser', - options={'ordering': ['name'], 'verbose_name': 'Admin user'}, + migrations.AddField( + model_name='favoriteasset', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), ), - migrations.AlterModelOptions( + migrations.AlterUniqueTogether( + name='domain', + unique_together={('org_id', 'name')}, + ), + migrations.AddField( + model_name='baseautomation', + name='assets', + field=models.ManyToManyField(blank=True, to='assets.asset', verbose_name='Assets'), + ), + migrations.AddField( + model_name='baseautomation', + name='nodes', + field=models.ManyToManyField(blank=True, to='assets.node', verbose_name='Node'), + ), + migrations.AddField( + model_name='automationexecution', + name='automation', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='executions', to='assets.baseautomation', verbose_name='Automation task'), + ), + migrations.AddField( + model_name='asset', + name='domain', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assets', to='assets.domain', verbose_name='Domain'), + ), + migrations.AddField( + model_name='asset', + name='nodes', + field=models.ManyToManyField(default=assets.models.asset.common.default_node, related_name='assets', to='assets.node', verbose_name='Nodes'), + ), + migrations.AddField( + model_name='asset', + name='platform', + field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='assets', to='assets.platform', verbose_name='Platform'), + ), + migrations.CreateModel( + name='AssetBaseAutomation', + fields=[ + ], + options={ + 'verbose_name': 'Asset automation task', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('assets.baseautomation',), + ), + migrations.CreateModel( + name='GatherFactsAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ], + options={ + 'verbose_name': 'Gather asset facts', + }, + bases=('assets.assetbaseautomation',), + ), + migrations.CreateModel( + name='PingAutomation', + fields=[ + ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), + ], + options={ + 'verbose_name': 'Ping asset', + }, + bases=('assets.assetbaseautomation',), + ), + migrations.AlterUniqueTogether( + name='favoriteasset', + unique_together={('user', 'asset')}, + ), + migrations.AlterUniqueTogether( + name='baseautomation', + unique_together={('org_id', 'name', 'type')}, + ), + migrations.AlterUniqueTogether( name='asset', - options={'verbose_name': 'Asset'}, + unique_together={('org_id', 'name')}, ), - migrations.AlterModelOptions( - name='assetgroup', - options={'ordering': ['name'], 'verbose_name': 'Asset group'}, - ), - migrations.AlterModelOptions( - name='cluster', - options={'ordering': ['name'], 'verbose_name': 'Cluster'}, - ), - migrations.AlterModelOptions( - name='systemuser', - options={'ordering': ['name'], 'verbose_name': 'System user'}, + migrations.CreateModel( + name='Gateway', + fields=[ + ], + options={ + 'verbose_name': 'Gateway', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('assets.host',), ), ] diff --git a/apps/assets/migrations/0002_auto_20180105_1807_squashed_0009_auto_20180307_1212.py b/apps/assets/migrations/0002_auto_20180105_1807_squashed_0009_auto_20180307_1212.py deleted file mode 100644 index 7cbf78a43..000000000 --- a/apps/assets/migrations/0002_auto_20180105_1807_squashed_0009_auto_20180307_1212.py +++ /dev/null @@ -1,158 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-28 10:16 - -import assets.models.asset -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - replaces = [('assets', '0002_auto_20180105_1807'), ('assets', '0003_auto_20180109_2331'), ('assets', '0004_auto_20180125_1218'), ('assets', '0005_auto_20180126_1637'), ('assets', '0006_auto_20180130_1502'), ('assets', '0007_auto_20180225_1815'), ('assets', '0008_auto_20180306_1804'), ('assets', '0009_auto_20180307_1212')] - - dependencies = [ - ('assets', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='adminuser', - options={'ordering': ['name'], 'verbose_name': 'Admin user'}, - ), - migrations.AlterModelOptions( - name='asset', - options={'verbose_name': 'Asset'}, - ), - migrations.AlterModelOptions( - name='assetgroup', - options={'ordering': ['name'], 'verbose_name': 'Asset group'}, - ), - migrations.AlterModelOptions( - name='cluster', - options={'ordering': ['name'], 'verbose_name': 'Cluster'}, - ), - migrations.AlterModelOptions( - name='systemuser', - options={'ordering': ['name'], 'verbose_name': 'System user'}, - ), - migrations.RemoveField( - model_name='asset', - name='cluster', - ), - migrations.AlterField( - model_name='assetgroup', - name='created_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'), - ), - migrations.CreateModel( - name='Label', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('value', models.CharField(max_length=128, verbose_name='Value')), - ('category', models.CharField(choices=[('S', 'System'), ('U', 'User')], default='U', max_length=128, verbose_name='Category')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('comment', models.TextField(blank=True, null=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ], - options={ - 'db_table': 'assets_label', - }, - ), - migrations.AlterUniqueTogether( - name='label', - unique_together={('name', 'value')}, - ), - migrations.AddField( - model_name='asset', - name='labels', - field=models.ManyToManyField(blank=True, related_name='assets', to='assets.Label', verbose_name='Labels'), - ), - migrations.RemoveField( - model_name='asset', - name='cabinet_no', - ), - migrations.RemoveField( - model_name='asset', - name='cabinet_pos', - ), - migrations.RemoveField( - model_name='asset', - name='env', - ), - migrations.RemoveField( - model_name='asset', - name='remote_card_ip', - ), - migrations.RemoveField( - model_name='asset', - name='status', - ), - migrations.RemoveField( - model_name='asset', - name='type', - ), - migrations.CreateModel( - name='Node', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('key', models.CharField(max_length=64, unique=True, verbose_name='Key')), - ('value', models.CharField(max_length=128, verbose_name='Value')), - ('child_mark', models.IntegerField(default=0)), - ('date_create', models.DateTimeField(auto_now_add=True)), - ], - ), - migrations.RemoveField( - model_name='asset', - name='groups', - ), - migrations.RemoveField( - model_name='systemuser', - name='cluster', - ), - migrations.AlterField( - model_name='asset', - name='admin_user', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='assets.AdminUser', verbose_name='Admin user'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.AddField( - model_name='asset', - name='nodes', - field=models.ManyToManyField(default=assets.models.asset.default_node, related_name='assets', to='assets.Node', verbose_name='Nodes'), - ), - migrations.AddField( - model_name='systemuser', - name='nodes', - field=models.ManyToManyField(blank=True, to='assets.Node', verbose_name='Nodes'), - ), - migrations.AlterField( - model_name='adminuser', - name='created_by', - field=models.CharField(max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='asset', - name='platform', - field=models.CharField(choices=[('Linux', 'Linux'), ('Unix', 'Unix'), ('MacOS', 'MacOS'), ('BSD', 'BSD'), ('Windows', 'Windows'), ('Other', 'Other')], default='Linux', max_length=128, verbose_name='Platform'), - ), - migrations.AlterField( - model_name='systemuser', - name='created_by', - field=models.CharField(max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=128, verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0003_auto_20180109_2331.py b/apps/assets/migrations/0003_auto_20180109_2331.py index 097bc607a..e23610dd2 100644 --- a/apps/assets/migrations/0003_auto_20180109_2331.py +++ b/apps/assets/migrations/0003_auto_20180109_2331.py @@ -1,10 +1,1257 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-09 15:31 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import assets.models.asset +import json +from functools import reduce +from django.db.models import F +from django.conf import settings from django.db import migrations, models -import django.db.models.deletion +from assets.const import AllTypes + +platforms_data_json = '''[ + { + "category": "host", + "type": "linux", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": true, + "name": "Linux", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "gather_facts_enabled": true, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "posix_ping", + "gather_facts_method": "gather_facts_posix", + "gather_accounts_method": "gather_accounts_posix", + "verify_account_method": "verify_account_posix", + "change_secret_method": "change_secret_posix", + "push_account_method": "push_account_posix" + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "telnet", + "port": 23, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "setting": { + "console": false, + "security": "any" + }, + "required": false, + "default": false + } + ] + }, + { + "category": "host", + "type": "linux", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": true, + "name": "Gateway", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "gather_facts_enabled": true, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "posix_ping", + "gather_facts_method": "gather_facts_posix", + "gather_accounts_method": "gather_accounts_posix", + "verify_account_method": "verify_account_posix", + "change_secret_method": "change_secret_posix", + "push_account_method": "push_account_posix" + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "telnet", + "port": 23, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "setting": { + "console": false, + "security": "any" + }, + "required": false, + "default": false + } + ] + }, + { + "category": "host", + "type": "unix", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": true, + "name": "Unix", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "gather_facts_enabled": true, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "posix_ping", + "gather_facts_method": "gather_facts_posix", + "gather_accounts_method": "gather_accounts_posix", + "verify_account_method": "verify_account_posix", + "change_secret_method": "change_secret_posix", + "push_account_method": "push_account_posix" + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "telnet", + "port": 23, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "setting": { + "console": false, + "security": "any" + }, + "required": false, + "default": false + } + ] + }, + { + "category": "host", + "type": "unix", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": true, + "name": "macOS", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "gather_facts_enabled": true, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "posix_ping", + "gather_facts_method": "gather_facts_posix", + "gather_accounts_method": "gather_accounts_posix", + "verify_account_method": "verify_account_posix", + "change_secret_method": "change_secret_posix", + "push_account_method": "push_account_posix" + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "telnet", + "port": 23, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "setting": { + "console": false, + "security": "any" + }, + "required": false, + "default": false + } + ] + }, + { + "category": "host", + "type": "unix", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": true, + "name": "BSD", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "gather_facts_enabled": true, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "posix_ping", + "gather_facts_method": "gather_facts_posix", + "gather_accounts_method": "gather_accounts_posix", + "verify_account_method": "verify_account_posix", + "change_secret_method": "change_secret_posix", + "push_account_method": "push_account_posix" + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "telnet", + "port": 23, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "setting": { + "console": false, + "security": "any" + }, + "required": false, + "default": false + } + ] + }, + { + "category": "host", + "type": "unix", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": true, + "name": "AIX", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "smart" + }, + "ping_enabled": true, + "gather_facts_enabled": true, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "posix_ping", + "gather_facts_method": "gather_facts_posix", + "gather_accounts_method": "gather_accounts_posix", + "verify_account_method": "verify_account_posix", + "change_secret_method": "change_secret_aix", + "push_account_method": "push_account_aix" + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "telnet", + "port": 23, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "vnc", + "port": 5900, + "required": false, + "default": false, + "setting": {} + }, + { + "name": "rdp", + "port": 3389, + "setting": { + "console": false, + "security": "any" + }, + "required": false, + "default": false + } + ] + }, + { + "category": "host", + "type": "windows", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "Windows", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_shell_type": "cmd", + "ansible_connection": "ssh" + }, + "ping_enabled": true, + "gather_facts_enabled": true, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "ping_by_rdp", + "gather_facts_method": "gather_facts_windows", + "gather_accounts_method": "gather_accounts_windows", + "verify_account_method": "verify_account_by_rdp", + "change_secret_method": "change_secret_local_windows", + "push_account_method": "push_account_local_windows" + }, + "protocols": [ + { + "name": "rdp", + "port": 3389, + "setting": { + "console": false, + "security": "any" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "required": false, + "default": false + }, + { + "name": "vnc", + "port": 5900, + "required": false, + "default": false, + "setting": {} + } + ] + }, + { + "category": "host", + "type": "windows", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "Windows-TLS", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_shell_type": "cmd", + "ansible_connection": "ssh" + }, + "ping_enabled": true, + "gather_facts_enabled": true, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "win_ping", + "gather_facts_method": "gather_facts_windows", + "gather_accounts_method": "gather_accounts_windows", + "verify_account_method": "verify_account_windows", + "change_secret_method": "change_secret_local_windows", + "push_account_method": "push_account_local_windows" + }, + "protocols": [ + { + "name": "rdp", + "port": 3389, + "setting": { + "console": false, + "security": "tls" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "required": false, + "default": false + }, + { + "name": "vnc", + "port": 5900, + "required": false, + "default": false, + "setting": {} + } + ] + }, + { + "category": "host", + "type": "windows", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "Windows-RDP", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_shell_type": "cmd", + "ansible_connection": "ssh" + }, + "ping_enabled": true, + "gather_facts_enabled": true, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "win_ping", + "gather_facts_method": "gather_facts_windows", + "gather_accounts_method": "gather_accounts_windows", + "verify_account_method": "verify_account_windows", + "change_secret_method": "change_secret_local_windows", + "push_account_method": "push_account_local_windows" + }, + "protocols": [ + { + "name": "rdp", + "port": 3389, + "setting": { + "console": false, + "security": "rdp" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "required": false, + "default": false + }, + { + "name": "vnc", + "port": 5900, + "required": false, + "default": false, + "setting": {} + } + ] + }, + { + "category": "host", + "type": "windows", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "RemoteAppHost", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_shell_type": "cmd", + "ansible_connection": "ssh" + }, + "ping_enabled": true, + "gather_facts_enabled": true, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "win_ping", + "gather_facts_method": "gather_facts_windows", + "gather_accounts_method": "gather_accounts_windows", + "verify_account_method": "verify_account_windows", + "change_secret_method": "change_secret_local_windows", + "push_account_method": "push_account_local_windows" + }, + "protocols": [ + { + "name": "rdp", + "port": 3389, + "setting": { + "console": false, + "security": "any" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "required": true, + "default": false + } + ] + }, + { + "category": "device", + "type": "general", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "General", + "automation": { + "ansible_enabled": false, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": false, + "gather_facts_enabled": false, + "gather_accounts_enabled": false, + "verify_account_enabled": false, + "change_secret_enabled": false, + "push_account_enabled": false + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "telnet", + "port": 23, + "required": false, + "default": false, + "setting": {} + } + ] + }, + { + "category": "device", + "type": "general", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "Cisco", + "automation": { + "ansible_enabled": false, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": false, + "gather_facts_enabled": false, + "gather_accounts_enabled": false, + "verify_account_enabled": false, + "change_secret_enabled": false, + "push_account_enabled": false + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "telnet", + "port": 23, + "required": false, + "default": false, + "setting": {} + } + ] + }, + { + "category": "device", + "type": "general", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "Huawei", + "automation": { + "ansible_enabled": false, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": false, + "gather_facts_enabled": false, + "gather_accounts_enabled": false, + "verify_account_enabled": false, + "change_secret_enabled": false, + "push_account_enabled": false + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "telnet", + "port": 23, + "required": false, + "default": false, + "setting": {} + } + ] + }, + { + "category": "device", + "type": "general", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "H3C", + "automation": { + "ansible_enabled": false, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": false, + "gather_facts_enabled": false, + "gather_accounts_enabled": false, + "verify_account_enabled": false, + "change_secret_enabled": false, + "push_account_enabled": false + }, + "protocols": [ + { + "name": "ssh", + "port": 22, + "setting": { + "sftp_enabled": true, + "sftp_home": "/tmp" + }, + "primary": true, + "required": false, + "default": false + }, + { + "name": "telnet", + "port": 23, + "required": false, + "default": false, + "setting": {} + } + ] + }, + { + "category": "database", + "type": "mysql", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "MySQL", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "gather_facts_enabled": false, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "mysql_ping", + "gather_accounts_method": "gather_accounts_mysql", + "verify_account_method": "verify_account_mysql", + "change_secret_method": "change_secret_mysql", + "push_account_method": "push_account_mysql" + }, + "protocols": [ + { + "name": "mysql", + "port": 3306, + "setting": {}, + "required": false, + "primary": true, + "default": false + } + ] + }, + { + "category": "database", + "type": "mariadb", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "MariaDB", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "gather_facts_enabled": false, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "mysql_ping", + "gather_accounts_method": "gather_accounts_mysql", + "verify_account_method": "verify_account_mysql", + "change_secret_method": "change_secret_mysql", + "push_account_method": "push_account_mysql" + }, + "protocols": [ + { + "name": "mariadb", + "port": 3306, + "required": false, + "primary": true, + "default": false, + "setting": {} + } + ] + }, + { + "category": "database", + "type": "postgresql", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "PostgreSQL", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "gather_facts_enabled": false, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "ping_postgresql", + "gather_accounts_method": "gather_accounts_postgresql", + "verify_account_method": "verify_account_postgresql", + "change_secret_method": "change_secret_postgresql", + "push_account_method": "push_account_postgresql" + }, + "protocols": [ + { + "name": "postgresql", + "port": 5432, + "required": false, + "primary": true, + "default": false, + "setting": {} + } + ] + }, + { + "category": "database", + "type": "oracle", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "Oracle", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "gather_facts_enabled": false, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "oracle_ping", + "gather_accounts_method": "gather_accounts_oracle", + "verify_account_method": "verify_account_oracle", + "change_secret_method": "change_secret_oracle", + "push_account_method": "push_account_oracle" + }, + "protocols": [ + { + "name": "oracle", + "port": 1521, + "required": false, + "primary": true, + "default": false, + "setting": {} + } + ] + }, + { + "category": "database", + "type": "sqlserver", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "SQLServer", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "gather_facts_enabled": false, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "sqlserver_ping", + "verify_account_method": "verify_account_sqlserver", + "change_secret_method": "change_secret_sqlserver", + "push_account_method": "push_account_sqlserver" + }, + "protocols": [ + { + "name": "sqlserver", + "port": 1433, + "required": false, + "primary": true, + "default": false, + "setting": {} + } + ] + }, + { + "category": "database", + "type": "clickhouse", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "ClickHouse", + "automation": { + "ansible_enabled": false, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": false, + "gather_facts_enabled": false, + "gather_accounts_enabled": false, + "verify_account_enabled": false, + "change_secret_enabled": false, + "push_account_enabled": false + }, + "protocols": [ + { + "name": "clickhouse", + "port": 9000, + "required": false, + "primary": true, + "default": false, + "setting": {} + } + ] + }, + { + "category": "database", + "type": "mongodb", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "MongoDB", + "automation": { + "ansible_enabled": true, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": true, + "gather_facts_enabled": false, + "gather_accounts_enabled": true, + "verify_account_enabled": true, + "change_secret_enabled": true, + "push_account_enabled": true, + "ping_method": "mongodb_ping", + "gather_accounts_method": "gather_accounts_mongodb", + "verify_account_method": "verify_account_mongodb", + "change_secret_method": "change_secret_mongodb", + "push_account_method": "push_account_mongodb" + }, + "protocols": [ + { + "name": "mongodb", + "port": 27017, + "required": false, + "primary": true, + "default": false, + "setting": {} + } + ] + }, + { + "category": "database", + "type": "redis", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "Redis", + "automation": { + "ansible_enabled": false, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": false, + "gather_facts_enabled": false, + "gather_accounts_enabled": false, + "verify_account_enabled": false, + "change_secret_enabled": false, + "push_account_enabled": false + }, + "protocols": [ + { + "name": "redis", + "port": 6379, + "required": false, + "setting": { + "auth_username": false + }, + "primary": true, + "default": false + } + ] + }, + { + "category": "database", + "type": "redis", + "internal": true, + "charset": "utf-8", + "domain_enabled": true, + "su_enabled": false, + "name": "Redis6+", + "automation": { + "ansible_enabled": false, + "ansible_config": { + "ansible_connection": "local" + }, + "ping_enabled": false, + "gather_facts_enabled": false, + "gather_accounts_enabled": false, + "verify_account_enabled": false, + "change_secret_enabled": false, + "push_account_enabled": false + }, + "protocols": [ + { + "name": "redis", + "port": 6379, + "required": false, + "setting": { + "auth_username": true + }, + "primary": true, + "default": false + } + ] + }, + { + "category": "web", + "type": "website", + "internal": true, + "charset": "utf-8", + "domain_enabled": false, + "su_enabled": false, + "name": "Website", + "automation": { + "ansible_enabled": false, + "ping_enabled": false, + "gather_facts_enabled": false, + "verify_account_enabled": false, + "change_secret_enabled": false, + "push_account_enabled": false, + "gather_accounts_enabled": false + }, + "protocols": [ + { + "name": "http", + "port": 80, + "setting": { + "username_selector": "name=username", + "password_selector": "name=password", + "submit_selector": "id=longin_button" + }, + "primary": true, + "required": false, + "default": false + } + ] + }, + { + "category": "cloud", + "type": "private", + "internal": true, + "charset": "utf-8", + "domain_enabled": false, + "su_enabled": false, + "name": "Vmware-vSphere", + "automation": { + "ansible_enabled": false, + "ansible_config": {}, + "gather_facts_enabled": false, + "verify_account_enabled": false, + "change_secret_enabled": false, + "push_account_enabled": false, + "gather_accounts_enabled": false + }, + "protocols": [ + { + "name": "http", + "port": 80, + "setting": { + "username_selector": "name=username", + "password_selector": "name=password", + "submit_selector": "id=longin_button" + }, + "primary": true, + "required": false, + "default": false + } + ] + }, + { + "category": "cloud", + "type": "k8s", + "internal": true, + "charset": "utf-8", + "domain_enabled": false, + "su_enabled": false, + "name": "Kubernetes", + "automation": { + "ansible_enabled": false, + "ansible_config": {}, + "gather_facts_enabled": false, + "verify_account_enabled": false, + "change_secret_enabled": false, + "push_account_enabled": false, + "gather_accounts_enabled": false + }, + "protocols": [ + { + "name": "k8s", + "port": 443, + "required": false, + "primary": true, + "default": false, + "setting": {} + } + ] + } +]''' + + +def create_internal_platforms(apps, *args): + platform_cls = apps.get_model('assets', 'Platform') + automation_cls = apps.get_model('assets', 'PlatformAutomation') + platforms_data = json.loads(platforms_data_json) + + for platform_data in platforms_data: + protocols = platform_data.pop('protocols', []) + platform_data['protocols'] = [p for p in protocols if p.pop('primary', True) is not None] + AllTypes.create_or_update_by_platform_data(platform_data, platform_cls=platform_cls, automation_cls=automation_cls) + + +def add_chatgpt_platform(apps, schema_editor): + platform_cls = apps.get_model('assets', 'Platform') + automation_cls = apps.get_model('assets', 'PlatformAutomation') + platform = platform_cls.objects.create( + name='ChatGPT', internal=True, category='gpt', type='chatgpt', + domain_enabled=False, su_enabled=False, comment='ChatGPT', + created_by='System', updated_by='System', + ) + platform.protocols.create(name='chatgpt', port=443, primary=True, setting={'api_mode': 'gpt-3.5-turbo'}) + automation_cls.objects.create(ansible_enabled=False, platform=platform) + + +def add_db2_platform(apps, schema_editor): + platform_cls = apps.get_model('assets', 'Platform') + automation_cls = apps.get_model('assets', 'PlatformAutomation') + platform, _ = platform_cls.objects.update_or_create( + name='DB2', defaults={ + 'name': 'DB2', 'category': 'database', + 'internal': True, 'type': 'db2', + 'domain_enabled': True, 'su_enabled': False, + 'su_method': None, 'comment': 'DB2', 'created_by': 'System', + 'updated_by': 'System', 'custom_fields': [] + } + ) + platform.protocols.update_or_create(name='db2', defaults={ + 'name': 'db2', 'port': 50000, 'primary': True, 'setting': {} + }) + automation_cls.objects.update_or_create(platform=platform, defaults={'ansible_enabled': False}) + + +def migrate_automation_ansible_remove_account(apps, *args): + automation_model = apps.get_model('assets', 'PlatformAutomation') + automation_map = { + ('oracle',): 'remove_account_oracle', + ('windows',): 'remove_account_windows', + ('mongodb',): 'remove_account_mongodb', + ('linux', 'unix'): 'remove_account_posix', + ('sqlserver',): 'remove_account_sqlserver', + ('mysql', 'mariadb'): 'remove_account_mysql', + ('postgresql',): 'remove_account_postgresql', + } + + update_objs = [] + types = list(reduce(lambda x, y: x + y, automation_map.keys())) + qs = automation_model.objects.filter(platform__type__in=types).annotate(tp=F('platform__type')) + for automation in qs: + for types, method in automation_map.items(): + if automation.tp in types: + automation.remove_account_enabled = True + automation.remove_account_method = method + break + update_objs.append(automation) + automation_model.objects.bulk_update(update_objs, ['remove_account_enabled', 'remove_account_method']) class Migration(migrations.Migration): @@ -14,4 +1261,9 @@ class Migration(migrations.Migration): ] operations = [ + migrations.RunPython(create_internal_platforms), + migrations.RunPython(add_chatgpt_platform), + migrations.RunPython(add_db2_platform), + migrations.RunPython(migrate_automation_ansible_remove_account), ] + diff --git a/apps/assets/migrations/0004_auto_20180125_1218.py b/apps/assets/migrations/0004_auto_20180125_1218.py deleted file mode 100644 index 1886fa499..000000000 --- a/apps/assets/migrations/0004_auto_20180125_1218.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-25 04:18 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0003_auto_20180109_2331'), - ] - - operations = [ - migrations.AlterField( - model_name='assetgroup', - name='created_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'), - ), - ] diff --git a/apps/assets/migrations/0005_auto_20180126_1637.py b/apps/assets/migrations/0005_auto_20180126_1637.py deleted file mode 100644 index 8db19e482..000000000 --- a/apps/assets/migrations/0005_auto_20180126_1637.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-26 08:37 -from __future__ import unicode_literals - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0004_auto_20180125_1218'), - ] - - operations = [ - migrations.CreateModel( - name='Label', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('value', models.CharField(max_length=128, verbose_name='Value')), - ('category', models.CharField(choices=[('S', 'System'), ('U', 'User')], default='U', max_length=128, verbose_name='Category')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('comment', models.TextField(blank=True, null=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ], - options={ - 'db_table': 'assets_label', - }, - ), - migrations.AlterUniqueTogether( - name='label', - unique_together=set([('name', 'value')]), - ), - migrations.AddField( - model_name='asset', - name='labels', - field=models.ManyToManyField(blank=True, related_name='assets', to='assets.Label', verbose_name='Labels'), - ), - ] diff --git a/apps/assets/migrations/0006_auto_20180130_1502.py b/apps/assets/migrations/0006_auto_20180130_1502.py deleted file mode 100644 index b77470d27..000000000 --- a/apps/assets/migrations/0006_auto_20180130_1502.py +++ /dev/null @@ -1,39 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-30 07:02 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0005_auto_20180126_1637'), - ] - - operations = [ - migrations.RemoveField( - model_name='asset', - name='cabinet_no', - ), - migrations.RemoveField( - model_name='asset', - name='cabinet_pos', - ), - migrations.RemoveField( - model_name='asset', - name='env', - ), - migrations.RemoveField( - model_name='asset', - name='remote_card_ip', - ), - migrations.RemoveField( - model_name='asset', - name='status', - ), - migrations.RemoveField( - model_name='asset', - name='type', - ), - ] diff --git a/apps/assets/migrations/0007_auto_20180225_1815.py b/apps/assets/migrations/0007_auto_20180225_1815.py deleted file mode 100644 index 1097dd182..000000000 --- a/apps/assets/migrations/0007_auto_20180225_1815.py +++ /dev/null @@ -1,60 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-02-25 10:15 -from __future__ import unicode_literals - -import assets.models.asset -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0006_auto_20180130_1502'), - ] - - operations = [ - migrations.CreateModel( - name='Node', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('key', models.CharField(max_length=64, unique=True, verbose_name='Key')), - ('value', models.CharField(max_length=128, unique=True, verbose_name='Value')), - ('child_mark', models.IntegerField(default=0)), - ('date_create', models.DateTimeField(auto_now_add=True)), - ], - ), - migrations.RemoveField( - model_name='asset', - name='cluster', - ), - migrations.RemoveField( - model_name='asset', - name='groups', - ), - migrations.RemoveField( - model_name='systemuser', - name='cluster', - ), - migrations.AlterField( - model_name='asset', - name='admin_user', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, to='assets.AdminUser', verbose_name='Admin user'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.AddField( - model_name='asset', - name='nodes', - field=models.ManyToManyField(default=assets.models.default_node, related_name='assets', to='assets.Node', verbose_name='Node'), - ), - migrations.AddField( - model_name='systemuser', - name='nodes', - field=models.ManyToManyField(blank=True, to='assets.Node', verbose_name='Nodes'), - ), - ] diff --git a/apps/assets/migrations/0008_auto_20180306_1804.py b/apps/assets/migrations/0008_auto_20180306_1804.py deleted file mode 100644 index 48d352619..000000000 --- a/apps/assets/migrations/0008_auto_20180306_1804.py +++ /dev/null @@ -1,40 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-03-06 10:04 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0007_auto_20180225_1815'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='created_by', - field=models.CharField(max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='asset', - name='platform', - field=models.CharField(choices=[('Linux', 'Linux'), ('Unix', 'Unix'), ('MacOS', 'MacOS'), ('BSD', 'BSD'), ('Windows', 'Windows'), ('Other', 'Other')], default='Linux', max_length=128, verbose_name='Platform'), - ), - migrations.AlterField( - model_name='systemuser', - name='created_by', - field=models.CharField(max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=128, verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0009_auto_20180307_1212.py b/apps/assets/migrations/0009_auto_20180307_1212.py deleted file mode 100644 index 08d770642..000000000 --- a/apps/assets/migrations/0009_auto_20180307_1212.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-03-07 04:12 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0008_auto_20180306_1804'), - ] - - operations = [ - migrations.AlterField( - model_name='node', - name='value', - field=models.CharField(max_length=128, verbose_name='Value'), - ), - ] diff --git a/apps/assets/migrations/0010_auto_20180307_1749.py b/apps/assets/migrations/0010_auto_20180307_1749.py deleted file mode 100644 index 5e6be0943..000000000 --- a/apps/assets/migrations/0010_auto_20180307_1749.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-03-07 09:49 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0009_auto_20180307_1212'), - ] - - operations = [ - migrations.AlterField( - model_name='node', - name='value', - field=models.CharField(max_length=128, unique=True, verbose_name='Value'), - ), - ] diff --git a/apps/assets/migrations/0010_auto_20180307_1749_squashed_0019_auto_20180816_1320.py b/apps/assets/migrations/0010_auto_20180307_1749_squashed_0019_auto_20180816_1320.py deleted file mode 100644 index 364e36d1f..000000000 --- a/apps/assets/migrations/0010_auto_20180307_1749_squashed_0019_auto_20180816_1320.py +++ /dev/null @@ -1,220 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-28 10:16 - -import assets.models.utils -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -# Functions from the following migrations need manual copying. -# Move them and any dependencies into this file, then update the -# RunPython operations to refer to the local versions: -# assets.migrations.0017_auto_20180702_1415 - -def migrate_win_to_ssh_protocol(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - db_alias = schema_editor.connection.alias - asset_model.objects.using(db_alias).filter(platform__startswith='Win').update(protocol='rdp') - - -class Migration(migrations.Migration): - - replaces = [('assets', '0010_auto_20180307_1749'), ('assets', '0011_auto_20180326_0957'), ('assets', '0012_auto_20180404_1302'), ('assets', '0013_auto_20180411_1135'), ('assets', '0014_auto_20180427_1245'), ('assets', '0015_auto_20180510_1235'), ('assets', '0016_auto_20180511_1203'), ('assets', '0017_auto_20180702_1415'), ('assets', '0018_auto_20180807_1116'), ('assets', '0019_auto_20180816_1320')] - - dependencies = [ - ('assets', '0009_auto_20180307_1212'), - ] - - operations = [ - migrations.AlterField( - model_name='node', - name='value', - field=models.CharField(max_length=128, unique=True, verbose_name='Value'), - ), - migrations.CreateModel( - name='Domain', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ], - ), - migrations.CreateModel( - name='Gateway', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('username', models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username')), - ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), - ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('ip', models.GenericIPAddressField(db_index=True, verbose_name='IP')), - ('port', models.IntegerField(default=22, verbose_name='Port')), - ('protocol', models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp')], default='ssh', max_length=16, verbose_name='Protocol')), - ('comment', models.CharField(blank=True, max_length=128, null=True, verbose_name='Comment')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Domain', verbose_name='Domain')), - ], - options={ - 'abstract': False, - }, - ), - migrations.AddField( - model_name='asset', - name='domain', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assets', to='assets.Domain', verbose_name='Domain'), - ), - migrations.AddField( - model_name='systemuser', - name='assets', - field=models.ManyToManyField(blank=True, to='assets.Asset', verbose_name='Assets'), - ), - migrations.AlterField( - model_name='systemuser', - name='sudo', - field=models.TextField(default='/bin/whoami', verbose_name='Sudo'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_-]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_-]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='node', - name='value', - field=models.CharField(max_length=128, verbose_name='Value'), - ), - migrations.AddField( - model_name='asset', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)')], default='ssh', max_length=128, verbose_name='Protocol'), - ), - migrations.AddField( - model_name='systemuser', - name='login_mode', - field=models.CharField(choices=[('auto', 'Automatic login'), ('manual', 'Manually login')], default='auto', max_length=10, verbose_name='Login mode'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='asset', - name='platform', - field=models.CharField(choices=[('Linux', 'Linux'), ('Unix', 'Unix'), ('MacOS', 'MacOS'), ('BSD', 'BSD'), ('Windows', 'Windows'), ('Windows2016', 'Windows(2016)'), ('Other', 'Other')], default='Linux', max_length=128, verbose_name='Platform'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.RunPython( - code=migrate_win_to_ssh_protocol, - ), - migrations.AddField( - model_name='adminuser', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='asset', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='domain', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='gateway', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='label', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='node', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='systemuser', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AlterField( - model_name='adminuser', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterField( - model_name='asset', - name='hostname', - field=models.CharField(max_length=128, verbose_name='Hostname'), - ), - migrations.AlterField( - model_name='gateway', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterField( - model_name='systemuser', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='adminuser', - unique_together={('name', 'org_id')}, - ), - migrations.AddField( - model_name='asset', - name='cpu_vcpus', - field=models.IntegerField(null=True, verbose_name='CPU vcpus'), - ), - migrations.AlterUniqueTogether( - name='asset', - unique_together={('org_id', 'hostname')}, - ), - migrations.AlterUniqueTogether( - name='gateway', - unique_together={('name', 'org_id')}, - ), - migrations.AlterUniqueTogether( - name='systemuser', - unique_together={('name', 'org_id')}, - ), - migrations.AlterUniqueTogether( - name='label', - unique_together={('name', 'value', 'org_id')}, - ), - ] diff --git a/apps/assets/migrations/0011_auto_20180326_0957.py b/apps/assets/migrations/0011_auto_20180326_0957.py deleted file mode 100644 index 07b9055dc..000000000 --- a/apps/assets/migrations/0011_auto_20180326_0957.py +++ /dev/null @@ -1,55 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-03-26 01:57 -from __future__ import unicode_literals - -import assets.models.utils -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0010_auto_20180307_1749'), - ] - - operations = [ - migrations.CreateModel( - name='Domain', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ], - ), - migrations.CreateModel( - name='Gateway', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('username', models.CharField(max_length=128, verbose_name='Username')), - ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), - ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('ip', models.GenericIPAddressField(db_index=True, verbose_name='IP')), - ('port', models.IntegerField(default=22, verbose_name='Port')), - ('protocol', models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp')], default='ssh', max_length=16, verbose_name='Protocol')), - ('comment', models.CharField(blank=True, max_length=128, null=True, verbose_name='Comment')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('domain', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Domain', verbose_name='Domain')), - ], - options={ - 'abstract': False, - }, - ), - migrations.AddField( - model_name='asset', - name='domain', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='assets', to='assets.Domain', verbose_name='Domain'), - ), - ] diff --git a/apps/assets/migrations/0012_auto_20180404_1302.py b/apps/assets/migrations/0012_auto_20180404_1302.py deleted file mode 100644 index 0ccb63e27..000000000 --- a/apps/assets/migrations/0012_auto_20180404_1302.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-04 05:02 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0011_auto_20180326_0957'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='domain', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assets', to='assets.Domain', verbose_name='Domain'), - ), - ] diff --git a/apps/assets/migrations/0013_auto_20180411_1135.py b/apps/assets/migrations/0013_auto_20180411_1135.py deleted file mode 100644 index baaf789bd..000000000 --- a/apps/assets/migrations/0013_auto_20180411_1135.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-11 03:35 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0012_auto_20180404_1302'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='assets', - field=models.ManyToManyField(blank=True, to='assets.Asset', verbose_name='Assets'), - ), - migrations.AlterField( - model_name='systemuser', - name='sudo', - field=models.TextField(default='/bin/whoami', verbose_name='Sudo'), - ), - ] diff --git a/apps/assets/migrations/0014_auto_20180427_1245.py b/apps/assets/migrations/0014_auto_20180427_1245.py deleted file mode 100644 index 735a50879..000000000 --- a/apps/assets/migrations/0014_auto_20180427_1245.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-27 04:45 -from __future__ import unicode_literals - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0013_auto_20180411_1135'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_-]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_-]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_-]*$', 'Special char not allowed')], verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0015_auto_20180510_1235.py b/apps/assets/migrations/0015_auto_20180510_1235.py deleted file mode 100644 index 81d12d2e4..000000000 --- a/apps/assets/migrations/0015_auto_20180510_1235.py +++ /dev/null @@ -1,31 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-05-10 04:35 -from __future__ import unicode_literals - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0014_auto_20180427_1245'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0016_auto_20180511_1203.py b/apps/assets/migrations/0016_auto_20180511_1203.py deleted file mode 100644 index 32f79a3c6..000000000 --- a/apps/assets/migrations/0016_auto_20180511_1203.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-05-11 04:03 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0015_auto_20180510_1235'), - ] - - operations = [ - migrations.AlterField( - model_name='node', - name='value', - field=models.CharField(max_length=128, verbose_name='Value'), - ), - ] diff --git a/apps/assets/migrations/0017_auto_20180702_1415.py b/apps/assets/migrations/0017_auto_20180702_1415.py deleted file mode 100644 index 9950424a6..000000000 --- a/apps/assets/migrations/0017_auto_20180702_1415.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-07-02 06:15 -from __future__ import unicode_literals - -import django.core.validators -from django.db import migrations, models - - -def migrate_win_to_ssh_protocol(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - db_alias = schema_editor.connection.alias - asset_model.objects.using(db_alias).filter(platform__startswith='Win').update(protocol='rdp') - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0016_auto_20180511_1203'), - ] - - operations = [ - migrations.AddField( - model_name='asset', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)')], default='ssh', max_length=128, verbose_name='Protocol'), - ), - migrations.AddField( - model_name='systemuser', - name='login_mode', - field=models.CharField(choices=[('auto', 'Automatic login'), ('manual', 'Manually login')], default='auto', max_length=10, verbose_name='Login mode'), - ), - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='asset', - name='platform', - field=models.CharField(choices=[('Linux', 'Linux'), ('Unix', 'Unix'), ('MacOS', 'MacOS'), ('BSD', 'BSD'), ('Windows', 'Windows'), ('Windows2016', 'Windows(2016)'), ('Other', 'Other')], default='Linux', max_length=128, verbose_name='Platform'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.RunPython(migrate_win_to_ssh_protocol), - ] diff --git a/apps/assets/migrations/0018_auto_20180807_1116.py b/apps/assets/migrations/0018_auto_20180807_1116.py deleted file mode 100644 index c4e848b43..000000000 --- a/apps/assets/migrations/0018_auto_20180807_1116.py +++ /dev/null @@ -1,84 +0,0 @@ -# Generated by Django 2.0.7 on 2018-08-07 03:16 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0017_auto_20180702_1415'), - ] - - operations = [ - migrations.AddField( - model_name='adminuser', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='asset', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='domain', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='gateway', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='label', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='node', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AddField( - model_name='systemuser', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AlterField( - model_name='adminuser', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterField( - model_name='asset', - name='hostname', - field=models.CharField(max_length=128, verbose_name='Hostname'), - ), - migrations.AlterField( - model_name='gateway', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterField( - model_name='systemuser', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='adminuser', - unique_together={('name', 'org_id')}, - ), - migrations.AlterUniqueTogether( - name='asset', - unique_together={('org_id', 'hostname')}, - ), - migrations.AlterUniqueTogether( - name='gateway', - unique_together={('name', 'org_id')}, - ), - migrations.AlterUniqueTogether( - name='systemuser', - unique_together={('name', 'org_id')}, - ), - ] diff --git a/apps/assets/migrations/0019_auto_20180816_1320.py b/apps/assets/migrations/0019_auto_20180816_1320.py deleted file mode 100644 index 0d468e511..000000000 --- a/apps/assets/migrations/0019_auto_20180816_1320.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.0.7 on 2018-08-16 05:20 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0018_auto_20180807_1116'), - ] - - operations = [ - migrations.AddField( - model_name='asset', - name='cpu_vcpus', - field=models.IntegerField(null=True, verbose_name='CPU vcpus'), - ), - migrations.AlterUniqueTogether( - name='label', - unique_together={('name', 'value', 'org_id')}, - ), - ] diff --git a/apps/assets/migrations/0020_auto_20180816_1652.py b/apps/assets/migrations/0020_auto_20180816_1652.py deleted file mode 100644 index 8639c4022..000000000 --- a/apps/assets/migrations/0020_auto_20180816_1652.py +++ /dev/null @@ -1,48 +0,0 @@ -# Generated by Django 2.0.7 on 2018-08-16 08:52 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0019_auto_20180816_1320'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='asset', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='domain', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='gateway', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='label', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='node', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='systemuser', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - ] diff --git a/apps/assets/migrations/0021_auto_20180903_1132.py b/apps/assets/migrations/0021_auto_20180903_1132.py deleted file mode 100644 index 5039d9822..000000000 --- a/apps/assets/migrations/0021_auto_20180903_1132.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 2.1 on 2018-09-03 03:32 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0020_auto_20180816_1652'), - ] - - operations = [ - migrations.AlterModelOptions( - name='domain', - options={'verbose_name': 'Zone'}, - ), - migrations.AlterModelOptions( - name='gateway', - options={'verbose_name': 'Gateway'}, - ), - migrations.AlterModelOptions( - name='node', - options={'verbose_name': 'Node'}, - ), - ] diff --git a/apps/assets/migrations/0022_auto_20181012_1717.py b/apps/assets/migrations/0022_auto_20181012_1717.py deleted file mode 100644 index 8849249ea..000000000 --- a/apps/assets/migrations/0022_auto_20181012_1717.py +++ /dev/null @@ -1,56 +0,0 @@ -# Generated by Django 2.1.1 on 2018-10-12 09:17 - -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0021_auto_20180903_1132'), - ] - - operations = [ - migrations.CreateModel( - name='CommandFilter', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=64, verbose_name='Name')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('created_by', models.CharField(blank=True, default='', max_length=128, verbose_name='Created by')), - ], - options={ - 'abstract': False, - }, - ), - migrations.CreateModel( - name='CommandFilterRule', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('type', models.CharField(choices=[('regex', 'Regex'), ('command', 'Command')], default='command', max_length=16, verbose_name='Type')), - ('priority', models.IntegerField(default=50, help_text='1-100, the lower will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), - ('content', models.TextField(help_text='One line one command', max_length=1024, verbose_name='Content')), - ('action', models.IntegerField(choices=[(0, 'Deny'), (1, 'Allow')], default=0, verbose_name='Action')), - ('comment', models.CharField(blank=True, default='', max_length=64, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(blank=True, default='', max_length=128, verbose_name='Created by')), - ('filter', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='rules', to='assets.CommandFilter', verbose_name='Filter')), - ], - options={ - 'ordering': ('priority', 'action'), - }, - ), - migrations.AddField( - model_name='systemuser', - name='cmd_filters', - field=models.ManyToManyField(blank=True, related_name='system_users', to='assets.CommandFilter', verbose_name='Command filter'), - ), - ] diff --git a/apps/assets/migrations/0023_auto_20181016_1650.py b/apps/assets/migrations/0023_auto_20181016_1650.py deleted file mode 100644 index f7ecd1b4f..000000000 --- a/apps/assets/migrations/0023_auto_20181016_1650.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.1.1 on 2018-10-16 08:50 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0022_auto_20181012_1717'), - ] - - operations = [ - migrations.AlterModelOptions( - name='commandfilterrule', - options={'ordering': ('-priority', 'action')}, - ), - migrations.AlterField( - model_name='commandfilterrule', - name='priority', - field=models.IntegerField(default=50, help_text='1-100, the higher will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority'), - ), - migrations.AlterField( - model_name='systemuser', - name='priority', - field=models.IntegerField(default=20, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority'), - ), - ] diff --git a/apps/assets/migrations/0024_auto_20181219_1614.py b/apps/assets/migrations/0024_auto_20181219_1614.py deleted file mode 100644 index 5e6a6c4e3..000000000 --- a/apps/assets/migrations/0024_auto_20181219_1614.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.1.4 on 2018-12-19 08:14 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0023_auto_20181016_1650'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)'), ('vnc', 'vnc')], default='ssh', max_length=128, verbose_name='Protocol'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)'), ('vnc', 'vnc')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0025_auto_20190221_1902.py b/apps/assets/migrations/0025_auto_20190221_1902.py deleted file mode 100644 index 7124bb509..000000000 --- a/apps/assets/migrations/0025_auto_20190221_1902.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-21 11:02 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0024_auto_20181219_1614'), - ] - - operations = [ - migrations.AlterModelOptions( - name='commandfilter', - options={'verbose_name': 'Command filter'}, - ), - migrations.AlterModelOptions( - name='commandfilterrule', - options={'ordering': ('-priority', 'action'), 'verbose_name': 'Command filter rule'}, - ), - ] diff --git a/apps/assets/migrations/0026_auto_20190325_2035.py b/apps/assets/migrations/0026_auto_20190325_2035.py deleted file mode 100644 index c329658e0..000000000 --- a/apps/assets/migrations/0026_auto_20190325_2035.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 2.1.7 on 2019-03-25 12:35 - -import assets.models.utils -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0025_auto_20190221_1902'), - ] - - operations = [ - migrations.CreateModel( - name='AuthBook', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('username', models.CharField(blank=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username')), - ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), - ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_updated', models.DateTimeField(auto_now=True)), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('is_latest', models.BooleanField(default=False, verbose_name='Latest version')), - ('version', models.IntegerField(default=1, verbose_name='Version')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset', verbose_name='Asset')), - ], - options={ - 'verbose_name': 'AuthBook', - }, - ), - migrations.AlterModelOptions( - name='node', - options={'ordering': ['key'], 'verbose_name': 'Node'}, - ), - ] diff --git a/apps/assets/migrations/0027_auto_20190521_1703.py b/apps/assets/migrations/0027_auto_20190521_1703.py deleted file mode 100644 index 91446019f..000000000 --- a/apps/assets/migrations/0027_auto_20190521_1703.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.1.7 on 2019-05-21 09:03 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0026_auto_20190325_2035'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='ip', - field=models.CharField(db_index=True, max_length=128, verbose_name='IP'), - ), - migrations.AlterField( - model_name='asset', - name='public_ip', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Public IP'), - ), - ] diff --git a/apps/assets/migrations/0028_protocol.py b/apps/assets/migrations/0028_protocol.py deleted file mode 100644 index 82b311c11..000000000 --- a/apps/assets/migrations/0028_protocol.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 2.1.7 on 2019-05-22 02:58 - -import uuid - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0027_auto_20190521_1703'), - ] - - operations = [ - migrations.CreateModel( - name='Protocol', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', - models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet (beta)'), ('vnc', 'vnc')], - default='ssh', max_length=16, verbose_name='Name')), - ('port', models.IntegerField(default=22, validators=[django.core.validators.MaxValueValidator(65535), - django.core.validators.MinValueValidator(0)], - verbose_name='Port')), - ], - ), - migrations.AddField( - model_name='asset', - name='protocols', - field=models.ManyToManyField(to='assets.Protocol', - verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0029_auto_20190522_1114.py b/apps/assets/migrations/0029_auto_20190522_1114.py deleted file mode 100644 index 46836c846..000000000 --- a/apps/assets/migrations/0029_auto_20190522_1114.py +++ /dev/null @@ -1,13 +0,0 @@ -# Generated by Django 2.1.7 on 2019-05-22 03:14 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0028_protocol'), - ] - - operations = [ - ] diff --git a/apps/assets/migrations/0030_auto_20190619_1135.py b/apps/assets/migrations/0030_auto_20190619_1135.py deleted file mode 100644 index a4b6969aa..000000000 --- a/apps/assets/migrations/0030_auto_20190619_1135.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-19 03:35 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0029_auto_20190522_1114'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='admin_user', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='assets', to='assets.AdminUser', verbose_name='Admin user'), - ), - ] diff --git a/apps/assets/migrations/0031_auto_20190621_1332.py b/apps/assets/migrations/0031_auto_20190621_1332.py deleted file mode 100644 index c2e614cbc..000000000 --- a/apps/assets/migrations/0031_auto_20190621_1332.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-21 05:32 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0030_auto_20190619_1135'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='date_created', - field=models.DateTimeField(auto_now_add=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='adminuser', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AlterField( - model_name='authbook', - name='date_created', - field=models.DateTimeField(auto_now_add=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='authbook', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AlterField( - model_name='gateway', - name='date_created', - field=models.DateTimeField(auto_now_add=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='gateway', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AlterField( - model_name='systemuser', - name='date_created', - field=models.DateTimeField(auto_now_add=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='systemuser', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - ] diff --git a/apps/assets/migrations/0032_auto_20190624_2108.py b/apps/assets/migrations/0032_auto_20190624_2108.py deleted file mode 100644 index 275308e99..000000000 --- a/apps/assets/migrations/0032_auto_20190624_2108.py +++ /dev/null @@ -1,75 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-24 13:08 - -import assets.models.utils -import common.db.fields -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0031_auto_20190621_1332'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='_password', - field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'), - ), - migrations.AlterField( - model_name='adminuser', - name='_private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='adminuser', - name='_public_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'), - ), - migrations.AlterField( - model_name='authbook', - name='_password', - field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'), - ), - migrations.AlterField( - model_name='authbook', - name='_private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='authbook', - name='_public_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'), - ), - migrations.AlterField( - model_name='gateway', - name='_password', - field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'), - ), - migrations.AlterField( - model_name='gateway', - name='_private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='gateway', - name='_public_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'), - ), - migrations.AlterField( - model_name='systemuser', - name='_password', - field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password'), - ), - migrations.AlterField( - model_name='systemuser', - name='_private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='systemuser', - name='_public_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key'), - ), - ] diff --git a/apps/assets/migrations/0033_auto_20190624_2108.py b/apps/assets/migrations/0033_auto_20190624_2108.py deleted file mode 100644 index dc89bc125..000000000 --- a/apps/assets/migrations/0033_auto_20190624_2108.py +++ /dev/null @@ -1,73 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-24 13:08 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0032_auto_20190624_2108'), - ] - - operations = [ - migrations.RenameField( - model_name='adminuser', - old_name='_private_key', - new_name='private_key', - ), - migrations.RenameField( - model_name='adminuser', - old_name='_public_key', - new_name='public_key', - ), - migrations.RenameField( - model_name='authbook', - old_name='_private_key', - new_name='private_key', - ), - migrations.RenameField( - model_name='authbook', - old_name='_public_key', - new_name='public_key', - ), - migrations.RenameField( - model_name='gateway', - old_name='_private_key', - new_name='private_key', - ), - migrations.RenameField( - model_name='gateway', - old_name='_public_key', - new_name='public_key', - ), - migrations.RenameField( - model_name='systemuser', - old_name='_private_key', - new_name='private_key', - ), - migrations.RenameField( - model_name='systemuser', - old_name='_public_key', - new_name='public_key', - ), - migrations.RenameField( - model_name='adminuser', - old_name='_password', - new_name='password', - ), - migrations.RenameField( - model_name='authbook', - old_name='_password', - new_name='password', - ), - migrations.RenameField( - model_name='gateway', - old_name='_password', - new_name='password', - ), - migrations.RenameField( - model_name='systemuser', - old_name='_password', - new_name='password', - ), - ] diff --git a/apps/assets/migrations/0034_auto_20190705_1348.py b/apps/assets/migrations/0034_auto_20190705_1348.py deleted file mode 100644 index 161ce2b30..000000000 --- a/apps/assets/migrations/0034_auto_20190705_1348.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-05 05:48 - -from django.db import migrations -from django.db.models import F -from django.db.models import CharField, Value as V -from django.db.models.functions import Concat - - -def migrate_assets_protocol(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - db_alias = schema_editor.connection.alias - assets = asset_model.objects.using(db_alias).all().annotate( - protocols_new=Concat( - 'protocol', V('/'), 'port', - output_field=CharField(), - ), - ) - assets.update(protocols=F('protocols_new')) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0033_auto_20190624_2108'), - ] - - operations = [ - migrations.RemoveField( - model_name='asset', - name='protocols', - ), - migrations.AddField( - model_name='asset', - name='protocols', - field=CharField(blank=True, default='ssh/22', max_length=128, verbose_name='Protocols'), - ), - migrations.RunPython(migrate_assets_protocol), - migrations.DeleteModel(name='Protocol'), - ] diff --git a/apps/assets/migrations/0035_auto_20190711_2018.py b/apps/assets/migrations/0035_auto_20190711_2018.py deleted file mode 100644 index 00eb41fe5..000000000 --- a/apps/assets/migrations/0035_auto_20190711_2018.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-11 12:18 - -import common.db.fields -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0034_auto_20190705_1348'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='authbook', - name='private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='gateway', - name='private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'), - ), - migrations.AlterField( - model_name='systemuser', - name='private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key'), - ), - ] diff --git a/apps/assets/migrations/0036_auto_20190716_1535.py b/apps/assets/migrations/0036_auto_20190716_1535.py deleted file mode 100644 index 317d427f0..000000000 --- a/apps/assets/migrations/0036_auto_20190716_1535.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-16 07:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0035_auto_20190711_2018'), - ] - - operations = [ - migrations.AlterField( - model_name='commandfilter', - name='name', - field=models.CharField(max_length=64, unique=True, verbose_name='Name'), - ), - ] diff --git a/apps/assets/migrations/0037_auto_20190724_2002.py b/apps/assets/migrations/0037_auto_20190724_2002.py deleted file mode 100644 index 49c5490c5..000000000 --- a/apps/assets/migrations/0037_auto_20190724_2002.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-24 12:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0036_auto_20190716_1535'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='_become_pass', - field=models.CharField(blank=True, default='', max_length=128), - ), - ] diff --git a/apps/assets/migrations/0038_auto_20190911_1634.py b/apps/assets/migrations/0038_auto_20190911_1634.py deleted file mode 100644 index 0533f5baf..000000000 --- a/apps/assets/migrations/0038_auto_20190911_1634.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-11 08:34 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0037_auto_20190724_2002'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet'), ('vnc', 'vnc')], default='ssh', max_length=128, verbose_name='Protocol'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet'), ('vnc', 'vnc')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0039_authbook_is_active.py b/apps/assets/migrations/0039_authbook_is_active.py deleted file mode 100644 index 3f600cfac..000000000 --- a/apps/assets/migrations/0039_authbook_is_active.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-17 12:22 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0038_auto_20190911_1634'), - ] - - operations = [ - migrations.AddField( - model_name='authbook', - name='is_active', - field=models.BooleanField(default=True, verbose_name='Is active'), - ), - ] diff --git a/apps/assets/migrations/0040_auto_20190917_2056.py b/apps/assets/migrations/0040_auto_20190917_2056.py deleted file mode 100644 index 2957a1f31..000000000 --- a/apps/assets/migrations/0040_auto_20190917_2056.py +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-17 12:56 - -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0039_authbook_is_active'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='authbook', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=32, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0041_gathereduser.py b/apps/assets/migrations/0041_gathereduser.py deleted file mode 100644 index f1b464e74..000000000 --- a/apps/assets/migrations/0041_gathereduser.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-18 04:10 - -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0040_auto_20190917_2056'), - ] - - operations = [ - migrations.CreateModel( - name='GatheredUser', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('username', models.CharField(blank=True, db_index=True, max_length=32, verbose_name='Username')), - ('present', models.BooleanField(default=True, verbose_name='Present')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset', verbose_name='Asset')), - ], - options={'ordering': ['asset'], 'verbose_name': 'GatherUser'}, - ), - ] diff --git a/apps/assets/migrations/0042_favoriteasset.py b/apps/assets/migrations/0042_favoriteasset.py deleted file mode 100644 index a09759e26..000000000 --- a/apps/assets/migrations/0042_favoriteasset.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 2.2.5 on 2019-10-16 08:38 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0041_gathereduser'), - ] - - operations = [ - migrations.CreateModel( - name='FavoriteAsset', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.Asset')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'unique_together': {('user', 'asset')}, - 'verbose_name': 'Favorite asset', - }, - ), - ] diff --git a/apps/assets/migrations/0043_auto_20191114_1111.py b/apps/assets/migrations/0043_auto_20191114_1111.py deleted file mode 100644 index 55a3eda47..000000000 --- a/apps/assets/migrations/0043_auto_20191114_1111.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.5 on 2019-11-14 03:11 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0042_favoriteasset'), - ] - - operations = [ - migrations.AddField( - model_name='gathereduser', - name='date_last_login', - field=models.DateTimeField(null=True, verbose_name='Date login'), - ), - migrations.AddField( - model_name='gathereduser', - name='ip_last_login', - field=models.CharField(default='', max_length=39, verbose_name='IP login'), - ), - ] diff --git a/apps/assets/migrations/0044_platform.py b/apps/assets/migrations/0044_platform.py deleted file mode 100644 index 2e1ab723e..000000000 --- a/apps/assets/migrations/0044_platform.py +++ /dev/null @@ -1,48 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-06 07:26 - -import common.db.fields -from django.db import migrations, models - - -def create_internal_platform(apps, schema_editor): - model = apps.get_model("assets", "Platform") - db_alias = schema_editor.connection.alias - type_platforms = ( - ('Linux', 'Linux', None), - ('Unix', 'Unix', None), - ('MacOS', 'MacOS', None), - ('BSD', 'BSD', None), - ('Windows', 'Windows', None), - ('Windows2016', 'Windows', {'security': 'tls'}), - ('Other', 'Other', None), - ) - for name, base, meta in type_platforms: - model.objects.using(db_alias).create( - name=name, base=base, internal=True, meta=meta - ) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0043_auto_20191114_1111'), - ] - - operations = [ - migrations.CreateModel( - name='Platform', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.SlugField(allow_unicode=True, unique=True, verbose_name='Name')), - ('base', models.CharField(choices=[('Linux', 'Linux'), ('Unix', 'Unix'), ('MacOS', 'MacOS'), ('BSD', 'BSD'), ('Windows', 'Windows'), ('Other', 'Other')], default='Linux', max_length=16, verbose_name='Base')), - ('charset', models.CharField(choices=[('utf8', 'UTF-8'), ('gbk', 'GBK')], default='utf8', max_length=8, verbose_name='Charset')), - ('meta', common.db.fields.JsonDictTextField(blank=True, null=True, verbose_name='Meta')), - ('internal', models.BooleanField(default=False, verbose_name='Internal')), - ('comment', models.TextField(blank=True, null=True, verbose_name='Comment')), - ], - options={ - 'verbose_name': 'Platform' - } - ), - migrations.RunPython(create_internal_platform) - ] diff --git a/apps/assets/migrations/0045_auto_20191206_1607.py b/apps/assets/migrations/0045_auto_20191206_1607.py deleted file mode 100644 index a2a136c3b..000000000 --- a/apps/assets/migrations/0045_auto_20191206_1607.py +++ /dev/null @@ -1,47 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-06 08:07 - -import assets.models.asset -from django.db import migrations, models -import django.db.models.deletion - - -def migrate_platform_to_asset_type(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - platform_model = apps.get_model("assets", "Platform") - db_alias = schema_editor.connection.alias - - platforms = platform_model.objects.using(db_alias).all() - platforms_map = {p.name: p for p in platforms} - for name, p in platforms_map.items(): - asset_model.objects.using(db_alias)\ - .filter(_platform=name)\ - .update(platform=p) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0044_platform'), - ] - - operations = [ - migrations.RenameField( - model_name='asset', - old_name='platform', - new_name='_platform', - ), - migrations.AddField( - model_name='asset', - name='platform', - field=models.ForeignKey( - default='', - on_delete=django.db.models.deletion.PROTECT, - related_name='assets', to='assets.Platform', - verbose_name='Platform'), - ), - migrations.RunPython(migrate_platform_to_asset_type), - migrations.RemoveField( - model_name='asset', - name='_platform', - ), - ] diff --git a/apps/assets/migrations/0046_auto_20191218_1705.py b/apps/assets/migrations/0046_auto_20191218_1705.py deleted file mode 100644 index af776eee2..000000000 --- a/apps/assets/migrations/0046_auto_20191218_1705.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.11 on 2019-12-18 09:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0045_auto_20191206_1607'), - ] - - operations = [ - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet'), ('vnc', 'vnc'), ('mysql', 'mysql')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0047_assetuser.py b/apps/assets/migrations/0047_assetuser.py deleted file mode 100644 index 6c309a0f7..000000000 --- a/apps/assets/migrations/0047_assetuser.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 2.2.7 on 2020-01-06 07:34 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0046_auto_20191218_1705'), - ] - - operations = [ - migrations.CreateModel( - name='AssetUser', - fields=[ - ], - options={ - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.authbook',), - ), - ] diff --git a/apps/assets/migrations/0048_auto_20191230_1512.py b/apps/assets/migrations/0048_auto_20191230_1512.py deleted file mode 100644 index b4bf9f9bc..000000000 --- a/apps/assets/migrations/0048_auto_20191230_1512.py +++ /dev/null @@ -1,35 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-30 07:12 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0047_assetuser'), - ] - - operations = [ - migrations.RemoveField( - model_name='authbook', - name='is_active', - ), - migrations.AddField( - model_name='systemuser', - name='username_same_with_user', - field=models.BooleanField(default=False, verbose_name='Username same with user'), - ), - migrations.AddField( - model_name='systemuser', - name='users', - field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Users'), - ), - migrations.AddField( - model_name='systemuser', - name='groups', - field=models.ManyToManyField(blank=True, to='users.UserGroup', - verbose_name='User groups'), - ), - ] diff --git a/apps/assets/migrations/0049_systemuser_sftp_root.py b/apps/assets/migrations/0049_systemuser_sftp_root.py deleted file mode 100644 index d8e992e25..000000000 --- a/apps/assets/migrations/0049_systemuser_sftp_root.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.7 on 2020-01-19 07:29 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0048_auto_20191230_1512'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='sftp_root', - field=models.CharField(default='tmp', max_length=128, verbose_name='SFTP Root'), - ), - ] diff --git a/apps/assets/migrations/0050_auto_20200711_1740.py b/apps/assets/migrations/0050_auto_20200711_1740.py deleted file mode 100644 index 231fcfbe4..000000000 --- a/apps/assets/migrations/0050_auto_20200711_1740.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-11 09:40 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0049_systemuser_sftp_root'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - ] diff --git a/apps/assets/migrations/0051_auto_20200713_1143.py b/apps/assets/migrations/0051_auto_20200713_1143.py deleted file mode 100644 index 95ec1ca06..000000000 --- a/apps/assets/migrations/0051_auto_20200713_1143.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-13 03:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0050_auto_20200711_1740'), - ] - - operations = [ - migrations.AlterField( - model_name='domain', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='domain', - unique_together={('org_id', 'name')}, - ), - ] diff --git a/apps/assets/migrations/0052_auto_20200715_1535.py b/apps/assets/migrations/0052_auto_20200715_1535.py deleted file mode 100644 index 5903d635e..000000000 --- a/apps/assets/migrations/0052_auto_20200715_1535.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-15 07:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0051_auto_20200713_1143'), - ] - - operations = [ - migrations.AlterField( - model_name='commandfilter', - name='name', - field=models.CharField(max_length=64, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='commandfilter', - unique_together={('org_id', 'name')}, - ), - ] diff --git a/apps/assets/migrations/0053_auto_20200723_1232.py b/apps/assets/migrations/0053_auto_20200723_1232.py deleted file mode 100644 index 7d1ba220d..000000000 --- a/apps/assets/migrations/0053_auto_20200723_1232.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-23 04:32 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0052_auto_20200715_1535'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='authbook', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0054_auto_20200807_1032.py b/apps/assets/migrations/0054_auto_20200807_1032.py deleted file mode 100644 index 288b78e25..000000000 --- a/apps/assets/migrations/0054_auto_20200807_1032.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-07 02:32 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0053_auto_20200723_1232'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='token', - field=models.TextField(default='', verbose_name='Token'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet'), ('vnc', 'vnc'), ('mysql', 'mysql'), ('k8s', 'k8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0055_auto_20200811_1845.py b/apps/assets/migrations/0055_auto_20200811_1845.py deleted file mode 100644 index 739378c78..000000000 --- a/apps/assets/migrations/0055_auto_20200811_1845.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-11 10:45 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0054_auto_20200807_1032'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='home', - field=models.CharField(blank=True, default='', max_length=4096, verbose_name='Home'), - ), - migrations.AddField( - model_name='systemuser', - name='system_groups', - field=models.CharField(blank=True, default='', max_length=4096, verbose_name='System groups'), - ), - ] diff --git a/apps/assets/migrations/0056_auto_20200904_1751.py b/apps/assets/migrations/0056_auto_20200904_1751.py deleted file mode 100644 index 1a7a34af1..000000000 --- a/apps/assets/migrations/0056_auto_20200904_1751.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.13 on 2020-09-04 09:51 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0055_auto_20200811_1845'), - ] - - operations = [ - migrations.AddField( - model_name='node', - name='assets_amount', - field=models.IntegerField(default=0), - ), - migrations.AddField( - model_name='node', - name='parent_key', - field=models.CharField(db_index=True, default='', max_length=64, verbose_name='Parent key'), - ), - ] diff --git a/apps/assets/migrations/0057_fill_node_value_assets_amount_and_parent_key.py b/apps/assets/migrations/0057_fill_node_value_assets_amount_and_parent_key.py deleted file mode 100644 index 458975692..000000000 --- a/apps/assets/migrations/0057_fill_node_value_assets_amount_and_parent_key.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-21 08:20 - -from django.db import migrations -from django.db.models import Q - - -def fill_node_value(apps, schema_editor): - Node = apps.get_model('assets', 'Node') - Asset = apps.get_model('assets', 'Asset') - node_queryset = Node.objects.all() - node_amount = node_queryset.count() - width = len(str(node_amount)) - print('\n') - for i, node in enumerate(node_queryset): - print(f'\t{i+1:0>{width}}/{node_amount} compute node[{node.key}]`s assets_amount ...') - assets_amount = Asset.objects.filter( - Q(nodes__key__istartswith=f'{node.key}:') | Q(nodes=node) - ).distinct().count() - key = node.key - try: - parent_key = key[:key.rindex(':')] - except ValueError: - parent_key = '' - node.assets_amount = assets_amount - node.parent_key = parent_key - node.save() - print(' ' + '.'*65, end='') - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0056_auto_20200904_1751'), - ] - - operations = [ - migrations.RunPython(fill_node_value) - ] diff --git a/apps/assets/migrations/0058_auto_20201023_1115.py b/apps/assets/migrations/0058_auto_20201023_1115.py deleted file mode 100644 index 57636611a..000000000 --- a/apps/assets/migrations/0058_auto_20201023_1115.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-23 03:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0057_fill_node_value_assets_amount_and_parent_key'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['-date_created'], 'verbose_name': 'Asset'}, - ), - migrations.AlterField( - model_name='asset', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='commandfilterrule', - name='content', - field=models.TextField(help_text='One line one command', verbose_name='Content'), - ), - ] diff --git a/apps/assets/migrations/0059_auto_20201027_1905.py b/apps/assets/migrations/0059_auto_20201027_1905.py deleted file mode 100644 index a01120fd7..000000000 --- a/apps/assets/migrations/0059_auto_20201027_1905.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-27 11:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0058_auto_20201023_1115'), - ] - - operations = [ - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('telnet', 'telnet'), ('vnc', 'vnc'), ('mysql', 'mysql'), ('oracle', 'oracle'), ('mariadb', 'mariadb'), ('postgresql', 'postgresql'), ('k8s', 'k8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.AddField( - model_name='systemuser', - name='ad_domain', - field=models.CharField(default='', max_length=256), - ), - migrations.AlterField( - model_name='gateway', - name='ip', - field=models.CharField(db_index=True, max_length=128, verbose_name='IP'), - ), - ] diff --git a/apps/assets/migrations/0060_node_full_value.py b/apps/assets/migrations/0060_node_full_value.py deleted file mode 100644 index 0f633deac..000000000 --- a/apps/assets/migrations/0060_node_full_value.py +++ /dev/null @@ -1,58 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-26 11:31 - -from django.db import migrations, models - - -def get_node_ancestor_keys(key, with_self=False): - parent_keys = [] - key_list = key.split(":") - if not with_self: - key_list.pop() - for i in range(len(key_list)): - parent_keys.append(":".join(key_list)) - key_list.pop() - return parent_keys - - -def migrate_nodes_value_with_slash(apps, schema_editor): - model = apps.get_model("assets", "Node") - db_alias = schema_editor.connection.alias - nodes = model.objects.using(db_alias).filter(value__contains='/') - print('') - print("\t- Start migrate node value if has /") - for i, node in enumerate(list(nodes)): - new_value = node.value.replace('/', '|') - print("\t - {} start migrate node value: {} => {}".format(i, node.value, new_value)) - node.value = new_value - node.save() - - -def migrate_nodes_full_value(apps, schema_editor): - model = apps.get_model("assets", "Node") - db_alias = schema_editor.connection.alias - nodes = model.objects.using(db_alias).all() - print("\n\t- Start migrate node full value") - for i, node in enumerate(list(nodes)): - print("\t - {} start migrate {} node full value".format(i, node.value)) - ancestor_keys = get_node_ancestor_keys(node.key, True) - values = model.objects.filter(key__in=ancestor_keys).values_list('key', 'value') - values = [v for k, v in sorted(values, key=lambda x: len(x[0]))] - node.full_value = '/' + '/'.join(values) - node.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0059_auto_20201027_1905'), - ] - - operations = [ - migrations.AddField( - model_name='node', - name='full_value', - field=models.CharField(default='', max_length=4096, verbose_name='Full value'), - ), - migrations.RunPython(migrate_nodes_value_with_slash), - migrations.RunPython(migrate_nodes_full_value) - ] diff --git a/apps/assets/migrations/0061_auto_20201116_1757.py b/apps/assets/migrations/0061_auto_20201116_1757.py deleted file mode 100644 index 71ddf21cf..000000000 --- a/apps/assets/migrations/0061_auto_20201116_1757.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.13 on 2020-11-16 09:57 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0060_node_full_value'), - ] - - operations = [ - migrations.AlterModelOptions( - name='node', - options={'ordering': ['value'], 'verbose_name': 'Node'}, - ), - ] diff --git a/apps/assets/migrations/0062_auto_20201117_1938.py b/apps/assets/migrations/0062_auto_20201117_1938.py deleted file mode 100644 index 9764ede39..000000000 --- a/apps/assets/migrations/0062_auto_20201117_1938.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.13 on 2020-11-17 11:38 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0061_auto_20201116_1757'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['hostname', 'ip'], 'verbose_name': 'Asset'}, - ), - ] diff --git a/apps/assets/migrations/0063_migrate_default_node_key.py b/apps/assets/migrations/0063_migrate_default_node_key.py deleted file mode 100644 index fc294264f..000000000 --- a/apps/assets/migrations/0063_migrate_default_node_key.py +++ /dev/null @@ -1,72 +0,0 @@ -# Generated by Jiangjie.Bai on 2020-12-01 10:47 - -from django.db import migrations -from django.db.models import Q - -default_node_value = 'Default' # Always -old_default_node_key = '0' # Version <= 1.4.3 -new_default_node_key = '1' # Version >= 1.4.4 - - -def compute_parent_key(key): - try: - return key[:key.rindex(':')] - except ValueError: - return '' - - -def migrate_default_node_key(apps, schema_editor): - """ 将已经存在的Default节点的key从0修改为1 """ - # 1.4.3版本中Default节点的key为0 - print('') - Node = apps.get_model('assets', 'Node') - Asset = apps.get_model('assets', 'Asset') - - # key为0的节点 - old_default_node = Node.objects.filter(key=old_default_node_key, value=default_node_value).first() - if not old_default_node: - print(f'Check old default node `key={old_default_node_key} value={default_node_value}` not exists') - return - print(f'Check old default node `key={old_default_node_key} value={default_node_value}` exists') - # key为1的节点 - new_default_node = Node.objects.filter(key=new_default_node_key, value=default_node_value).first() - if new_default_node: - print(f'Check new default node `key={new_default_node_key} value={default_node_value}` exists') - all_assets = Asset.objects.filter( - Q(nodes__key__startswith=f'{new_default_node_key}:') | Q(nodes__key=new_default_node_key) - ).distinct() - if all_assets: - print(f'Check new default node has assets (count: {len(all_assets)})') - return - all_children = Node.objects.filter(key__startswith=f'{new_default_node_key}:') - if all_children: - print(f'Check new default node has children nodes (count: {len(all_children)})') - return - print(f'Check new default node not has assets and children nodes, delete it.') - new_default_node.delete() - # 执行修改 - print(f'Modify old default node `key` from `{old_default_node_key}` to `{new_default_node_key}`') - nodes = Node.objects.filter( - Q(key__istartswith=f'{old_default_node_key}:') | Q(key=old_default_node_key) - ) - for node in nodes: - old_key = node.key - key_list = old_key.split(':', maxsplit=1) - key_list[0] = new_default_node_key - new_key = ':'.join(key_list) - node.key = new_key - node.parent_key = compute_parent_key(node.key) - # 批量更新 - print(f'Bulk update nodes `key` and `parent_key`, (count: {len(nodes)})') - Node.objects.bulk_update(nodes, ['key', 'parent_key']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0062_auto_20201117_1938'), - ] - - operations = [ - migrations.RunPython(migrate_default_node_key) - ] diff --git a/apps/assets/migrations/0064_auto_20201203_1100.py b/apps/assets/migrations/0064_auto_20201203_1100.py deleted file mode 100644 index a8119a883..000000000 --- a/apps/assets/migrations/0064_auto_20201203_1100.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1 on 2020-12-03 03:00 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0063_migrate_default_node_key'), - ] - - operations = [ - migrations.AlterModelOptions( - name='node', - options={'ordering': ['parent_key', 'value'], 'verbose_name': 'Node'}, - ), - ] diff --git a/apps/assets/migrations/0065_auto_20210121_1549.py b/apps/assets/migrations/0065_auto_20210121_1549.py deleted file mode 100644 index 687d4412b..000000000 --- a/apps/assets/migrations/0065_auto_20210121_1549.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1 on 2021-01-21 07:49 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0064_auto_20201203_1100'), - ] - - operations = [ - migrations.AlterModelOptions( - name='domain', - options={'ordering': ('name',), 'verbose_name': 'Zone'}, - ), - ] diff --git a/apps/assets/migrations/0066_auto_20210208_1802.py b/apps/assets/migrations/0066_auto_20210208_1802.py deleted file mode 100644 index ffe7d8fb5..000000000 --- a/apps/assets/migrations/0066_auto_20210208_1802.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1 on 2021-02-08 10:02 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0065_auto_20210121_1549'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['hostname'], 'verbose_name': 'Asset'}, - ), - ] diff --git a/apps/assets/migrations/0067_auto_20210311_1113.py b/apps/assets/migrations/0067_auto_20210311_1113.py deleted file mode 100644 index 0b087d47c..000000000 --- a/apps/assets/migrations/0067_auto_20210311_1113.py +++ /dev/null @@ -1,48 +0,0 @@ -# Generated by Django 3.1 on 2021-03-11 03:13 - -import django.core.validators -from django.db import migrations, models - - -def migrate_cmd_filter_priority(apps, schema_editor): - cmd_filter_rule_model = apps.get_model('assets', 'CommandFilterRule') - cmd_filter_rules = cmd_filter_rule_model.objects.all() - for cmd_filter_rule in cmd_filter_rules: - cmd_filter_rule.priority = 100 - cmd_filter_rule.priority + 1 - - cmd_filter_rule_model.objects.bulk_update(cmd_filter_rules, fields=['priority']) - - -def migrate_system_user_priority(apps, schema_editor): - system_user_model = apps.get_model('assets', 'SystemUser') - system_users = system_user_model.objects.all() - for system_user in system_users: - system_user.priority = 100 - system_user.priority + 1 - - system_user_model.objects.bulk_update(system_users, fields=['priority']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0066_auto_20210208_1802'), - ] - - operations = [ - migrations.RunPython(migrate_cmd_filter_priority), - migrations.RunPython(migrate_system_user_priority), - migrations.AlterModelOptions( - name='commandfilterrule', - options={'ordering': ('priority', 'action'), 'verbose_name': 'Command filter rule'}, - ), - migrations.AlterField( - model_name='commandfilterrule', - name='priority', - field=models.IntegerField(default=50, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority'), - ), - migrations.AlterField( - model_name='systemuser', - name='priority', - field=models.IntegerField(default=20, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority'), - ), - ] diff --git a/apps/assets/migrations/0068_auto_20210312_1455.py b/apps/assets/migrations/0068_auto_20210312_1455.py deleted file mode 100644 index 28d85ab9d..000000000 --- a/apps/assets/migrations/0068_auto_20210312_1455.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.1 on 2021-03-12 06:55 - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0067_auto_20210311_1113'), - ] - - operations = [ - migrations.AlterField( - model_name='systemuser', - name='priority', - field=models.IntegerField(default=81, help_text='1-100, the lower the value will be match first', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority'), - ), - ] diff --git a/apps/assets/migrations/0069_change_node_key0_to_key1.py b/apps/assets/migrations/0069_change_node_key0_to_key1.py deleted file mode 100644 index deb9b0e70..000000000 --- a/apps/assets/migrations/0069_change_node_key0_to_key1.py +++ /dev/null @@ -1,61 +0,0 @@ -from django.db import migrations -from django.db.transaction import atomic - -default_id = '00000000-0000-0000-0000-000000000002' - - -def change_key0_to_key1(apps, schema_editor): - from orgs.utils import set_current_org - - # https://stackoverflow.com/questions/28777338/django-migrations-runpython-not-able-to-call-model-methods - Organization = apps.get_model('orgs', 'Organization') - Node = apps.get_model('assets', 'Node') - - print() - org = Organization.objects.get(id=default_id) - set_current_org(org) - - exists_0 = Node.objects.filter(key__startswith='0').exists() - if not exists_0: - print(f'--> Not exist key=0 nodes, do nothing.') - return - - key_1_count = Node.objects.filter(key__startswith='1').count() - if key_1_count > 1: - print(f'--> Node key=1 have children, can`t just delete it. Please contact JumpServer team') - return - - root_node = Node.objects.filter(key='1').first() - if root_node and root_node.assets.exists(): - print(f'--> Node key=1 has assets, do nothing.') - return - - with atomic(): - if root_node: - print(f'--> Delete node key=1') - root_node.delete() - - nodes_0 = Node.objects.filter(key__startswith='0') - - for n in nodes_0: - old_key = n.key - key_list = n.key.split(':') - key_list[0] = '1' - new_key = ':'.join(key_list) - new_parent_key = ':'.join(key_list[:-1]) - n.key = new_key - n.parent_key = new_parent_key - n.save() - print('--> Modify key ( {} > {} )'.format(old_key, new_key)) - - -class Migration(migrations.Migration): - - dependencies = [ - ('orgs', '0010_auto_20210219_1241'), - ('assets', '0068_auto_20210312_1455'), - ] - - operations = [ - migrations.RunPython(change_key0_to_key1) - ] diff --git a/apps/assets/migrations/0070_auto_20210426_1515.py b/apps/assets/migrations/0070_auto_20210426_1515.py deleted file mode 100644 index ca6ff4273..000000000 --- a/apps/assets/migrations/0070_auto_20210426_1515.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1 on 2021-04-26 07:15 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0069_change_node_key0_to_key1'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilterrule', - name='reviewers', - field=models.ManyToManyField(blank=True, related_name='review_cmd_filter_rules', to=settings.AUTH_USER_MODEL, verbose_name='Reviewers'), - ), - migrations.AlterField( - model_name='commandfilterrule', - name='action', - field=models.IntegerField(choices=[(0, 'Deny'), (1, 'Allow'), (2, 'Reconfirm')], default=0, verbose_name='Action'), - ), - ] diff --git a/apps/assets/migrations/0071_systemuser_type.py b/apps/assets/migrations/0071_systemuser_type.py deleted file mode 100644 index 9dc48fa7a..000000000 --- a/apps/assets/migrations/0071_systemuser_type.py +++ /dev/null @@ -1,104 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-04 16:46 -import uuid -from django.db import migrations, models, transaction -import django.db.models.deletion -from django.db import IntegrityError -from django.db.models import F - - -def migrate_admin_user_to_system_user(apps, schema_editor): - admin_user_model = apps.get_model("assets", "AdminUser") - system_user_model = apps.get_model("assets", "SystemUser") - db_alias = schema_editor.connection.alias - - admin_users = admin_user_model.objects.using(db_alias).all() - print() - for admin_user in admin_users: - kwargs = {} - for attr in [ - 'org_id', 'username', 'password', 'private_key', 'public_key', - 'comment', 'date_created', 'date_updated', 'created_by', - ]: - value = getattr(admin_user, attr) - kwargs[attr] = value - - name = admin_user.name - exist = system_user_model.objects.using(db_alias).filter( - name=admin_user.name, org_id=admin_user.org_id - ).exists() - if exist: - name = admin_user.name + '_' + str(admin_user.id)[:5] - - i = admin_user.id - exist = system_user_model.objects.using(db_alias).filter( - id=i, org_id=admin_user.org_id - ).exists() - if exist: - i = uuid.uuid4() - - kwargs.update({ - 'id': i, - 'name': name, - 'type': 'admin', - 'protocol': 'ssh', - 'auto_push': False, - }) - - with transaction.atomic(): - s = system_user_model(**kwargs) - try: - s.save() - except IntegrityError: - s.id = None - s.save() - print(" Migrate admin user to system user: {} => {}".format(admin_user.name, s.name)) - assets = admin_user.assets.all() - s.assets.set(assets) - - -def migrate_assets_admin_user(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - db_alias = schema_editor.connection.alias - assets = asset_model.objects.using(db_alias).all() - assets.update(admin_user=F('_admin_user')) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0070_auto_20210426_1515'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='type', - field=models.CharField(choices=[('common', 'Common user'), ('admin', 'Admin user')], default='common', max_length=16, verbose_name='Type'), - ), - migrations.AlterField( - model_name='systemuser', - name='login_mode', - field=models.CharField(choices=[('auto', 'Automatic managed'), ('manual', 'Manually input')], default='auto', max_length=10, verbose_name='Login mode'), - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('k8s', 'K8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.RunPython(migrate_admin_user_to_system_user), - migrations.RenameField( - model_name='asset', - old_name='admin_user', - new_name='_admin_user', - ), - migrations.AddField( - model_name='asset', - name='admin_user', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='admin_assets', to='assets.systemuser', verbose_name='Admin user'), - ), - migrations.RunPython(migrate_assets_admin_user), - migrations.RemoveField( - model_name='asset', - name='_admin_user', - ), - ] diff --git a/apps/assets/migrations/0072_historicalauthbook.py b/apps/assets/migrations/0072_historicalauthbook.py deleted file mode 100644 index e28949c1f..000000000 --- a/apps/assets/migrations/0072_historicalauthbook.py +++ /dev/null @@ -1,85 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-05 16:10 - -import common.db.fields -from django.conf import settings -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import simple_history.models -import uuid -from django.utils import timezone -from django.db import migrations, transaction - - -def migrate_old_authbook_to_history(apps, schema_editor): - authbook_model = apps.get_model("assets", "AuthBook") - history_model = apps.get_model("assets", "HistoricalAuthBook") - db_alias = schema_editor.connection.alias - - print() - while True: - authbooks = authbook_model.objects.using(db_alias).filter(is_latest=False)[:1000] - if not authbooks: - break - historys = [] - authbook_ids = [] - # Todo: 或许能优化成更新那样 - for authbook in authbooks: - authbook_ids.append(authbook.id) - history = history_model() - - for attr in [ - 'id', 'username', 'password', 'private_key', 'public_key', 'version', - 'comment', 'created_by', 'asset', 'date_created', 'date_updated' - ]: - setattr(history, attr, getattr(authbook, attr)) - history.history_type = '-' - history.history_date = timezone.now() - historys.append(history) - - with transaction.atomic(): - print(" Migrate old auth book to history table: {} items".format(len(authbook_ids))) - history_model.objects.bulk_create(historys, ignore_conflicts=True) - authbook_model.objects.filter(id__in=authbook_ids).delete() - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0071_systemuser_type'), - ] - - operations = [ - migrations.CreateModel( - name='HistoricalAuthBook', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(db_index=True, default=uuid.uuid4)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('username', models.CharField(blank=True, db_index=True, max_length=128, validators=[django.core.validators.RegexValidator('^[0-9a-zA-Z_@\\-\\.]*$', 'Special char not allowed')], verbose_name='Username')), - ('password', common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Password')), - ('private_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH private key')), - ('public_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='SSH public key')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('date_created', models.DateTimeField(blank=True, editable=False, verbose_name='Date created')), - ('date_updated', models.DateTimeField(blank=True, editable=False, verbose_name='Date updated')), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('version', models.IntegerField(default=1, verbose_name='Version')), - ('is_latest', models.BooleanField(default=False, verbose_name='Latest version')), - ('history_id', models.AutoField(primary_key=True, serialize=False)), - ('history_date', models.DateTimeField()), - ('history_change_reason', models.CharField(max_length=100, null=True)), - ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), - ('asset', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='assets.asset', verbose_name='Asset')), - ('history_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'verbose_name': 'historical AuthBook', - 'ordering': ('-history_date', '-history_id'), - 'get_latest_by': 'history_date', - }, - bases=(simple_history.models.HistoricalChanges, models.Model), - ), - migrations.RunPython(migrate_old_authbook_to_history) - ] diff --git a/apps/assets/migrations/0073_auto_20210606_1142.py b/apps/assets/migrations/0073_auto_20210606_1142.py deleted file mode 100644 index ee4e214d9..000000000 --- a/apps/assets/migrations/0073_auto_20210606_1142.py +++ /dev/null @@ -1,105 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-06 03:42 - -from django.utils import timezone -from django.db import migrations, models, transaction -import django.db.models.deletion - - -def migrate_system_assets_to_authbook(apps, schema_editor): - system_user_model = apps.get_model("assets", "SystemUser") - system_user_asset_model = system_user_model.assets.through - authbook_model = apps.get_model('assets', 'AuthBook') - history_model = apps.get_model("assets", "HistoricalAuthBook") - - print() - system_users = system_user_model.objects.all() - for s in system_users: - while True: - systemuser_asset_relations = system_user_asset_model.objects.filter(systemuser=s)[:1000] - if not systemuser_asset_relations: - break - authbooks = [] - relations_ids = [] - historys = [] - for i in systemuser_asset_relations: - authbook = authbook_model(asset=i.asset, systemuser=i.systemuser, org_id=s.org_id) - authbooks.append(authbook) - relations_ids.append(i.id) - - history = history_model( - asset=i.asset, systemuser=i.systemuser, - date_created=timezone.now(), date_updated=timezone.now(), - ) - history.history_type = '-' - history.history_date = timezone.now() - historys.append(history) - - with transaction.atomic(): - print(" Migrate system user assets relations: {} items".format(len(relations_ids))) - authbook_model.objects.bulk_create(authbooks, ignore_conflicts=True) - history_model.objects.bulk_create(historys) - system_user_asset_model.objects.filter(id__in=relations_ids).delete() - - -def migrate_authbook_secret_to_system_user(apps, schema_editor): - authbook_model = apps.get_model('assets', 'AuthBook') - history_model = apps.get_model('assets', 'HistoricalAuthBook') - - print() - authbooks_without_systemuser = authbook_model.objects.filter(systemuser__isnull=True) - for authbook in authbooks_without_systemuser: - matched = authbook_model.objects.filter( - asset=authbook.asset, systemuser__username=authbook.username - ) - if not matched: - continue - historys = [] - for i in matched: - history = history_model( - asset=i.asset, systemuser=i.systemuser, - date_created=timezone.now(), date_updated=timezone.now(), - version=authbook.version - ) - history.history_type = '-' - history.history_date = timezone.now() - historys.append(history) - - with transaction.atomic(): - print(" Migrate secret to system user assets account: {} items".format(len(historys))) - matched.update(password=authbook.password, private_key=authbook.private_key, - public_key=authbook.public_key, version=authbook.version) - history_model.objects.bulk_create(historys) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0072_historicalauthbook'), - ] - - operations = [ - migrations.AddField( - model_name='authbook', - name='systemuser', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.systemuser', verbose_name='System user'), - ), - migrations.AddField( - model_name='historicalauthbook', - name='systemuser', - field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='assets.systemuser', verbose_name='System user'), - ), - migrations.AlterUniqueTogether( - name='authbook', - unique_together={('username', 'asset', 'systemuser')}, - ), - migrations.RunPython(migrate_system_assets_to_authbook), - migrations.RunPython(migrate_authbook_secret_to_system_user), - migrations.RemoveField( - model_name='authbook', - name='is_latest', - ), - migrations.RemoveField( - model_name='historicalauthbook', - name='is_latest', - ), - ] diff --git a/apps/assets/migrations/0074_remove_systemuser_assets.py b/apps/assets/migrations/0074_remove_systemuser_assets.py deleted file mode 100644 index 250c31b34..000000000 --- a/apps/assets/migrations/0074_remove_systemuser_assets.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-06 03:40 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0073_auto_20210606_1142'), - ] - - operations = [ - migrations.RemoveField( - model_name='systemuser', - name='assets', - ), - - migrations.AddField( - model_name='systemuser', - name='assets', - field=models.ManyToManyField(blank=True, related_name='system_users', through='assets.AuthBook', to='assets.Asset', verbose_name='Assets'), - ), - ] diff --git a/apps/assets/migrations/0075_auto_20210705_1759.py b/apps/assets/migrations/0075_auto_20210705_1759.py deleted file mode 100644 index 686d61bf0..000000000 --- a/apps/assets/migrations/0075_auto_20210705_1759.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 3.1 on 2021-07-05 09:59 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0074_remove_systemuser_assets'), - ] - - operations = [ - migrations.AddField( - model_name='asset', - name='connectivity', - field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'), - ), - migrations.AddField( - model_name='asset', - name='date_verified', - field=models.DateTimeField(null=True, verbose_name='Date verified'), - ), - migrations.AddField( - model_name='authbook', - name='connectivity', - field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'), - ), - migrations.AddField( - model_name='authbook', - name='date_verified', - field=models.DateTimeField(null=True, verbose_name='Date verified'), - ), - migrations.AddField( - model_name='historicalauthbook', - name='connectivity', - field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'), - ), - migrations.AddField( - model_name='historicalauthbook', - name='date_verified', - field=models.DateTimeField(null=True, verbose_name='Date verified'), - ), - migrations.AlterField( - model_name='asset', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC')], default='ssh', max_length=128, verbose_name='Protocol'), - ), - migrations.AlterField( - model_name='gateway', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0076_delete_assetuser.py b/apps/assets/migrations/0076_delete_assetuser.py deleted file mode 100644 index 75fdebd7f..000000000 --- a/apps/assets/migrations/0076_delete_assetuser.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 3.1.6 on 2021-07-12 02:25 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0075_auto_20210705_1759'), - ] - - operations = [ - migrations.DeleteModel( - name='AssetUser', - ), - ] diff --git a/apps/assets/migrations/0077_auto_20211012_1642.py b/apps/assets/migrations/0077_auto_20211012_1642.py deleted file mode 100644 index 6c56917e0..000000000 --- a/apps/assets/migrations/0077_auto_20211012_1642.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.1.12 on 2021-10-12 08:42 - -from django.db import migrations - - -def migrate_platform_win2016(apps, schema_editor): - platform_model = apps.get_model("assets", "Platform") - win2016 = platform_model.objects.filter(name='Windows2016').first() - if not win2016: - print("Error: Not found Windows2016 platform") - return - win2016.meta = {"security": "any"} - win2016.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0076_delete_assetuser'), - ] - - operations = [ - migrations.RunPython(migrate_platform_win2016) - ] diff --git a/apps/assets/migrations/0078_auto_20211014_2209.py b/apps/assets/migrations/0078_auto_20211014_2209.py deleted file mode 100644 index b2c1cf371..000000000 --- a/apps/assets/migrations/0078_auto_20211014_2209.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 3.1.13 on 2021-10-14 14:09 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0077_auto_20211012_1642'), - ] - - operations = [ - migrations.AlterField( - model_name='adminuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='authbook', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='gateway', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='historicalauthbook', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - migrations.AlterField( - model_name='systemuser', - name='username', - field=models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username'), - ), - ] diff --git a/apps/assets/migrations/0079_auto_20211102_1922.py b/apps/assets/migrations/0079_auto_20211102_1922.py deleted file mode 100644 index 592df0259..000000000 --- a/apps/assets/migrations/0079_auto_20211102_1922.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.1.12 on 2021-11-02 11:22 - -from django.db import migrations - - -def create_internal_platform(apps, schema_editor): - model = apps.get_model("assets", "Platform") - db_alias = schema_editor.connection.alias - type_platforms = ( - ('Windows-RDP', 'Windows', {'security': 'rdp'}), - ('Windows-TLS', 'Windows', {'security': 'tls'}), - ) - for name, base, meta in type_platforms: - defaults = {'name': name, 'base': base, 'meta': meta, 'internal': True} - model.objects.using(db_alias).update_or_create( - name=name, defaults=defaults - ) - - win2016 = model.objects.filter(name='Windows2016').first() - if win2016: - win2016.internal = False - win2016.save(update_fields=['internal']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0078_auto_20211014_2209'), - ] - - operations = [ - migrations.RunPython(create_internal_platform) - ] diff --git a/apps/assets/migrations/0080_auto_20211104_1347.py b/apps/assets/migrations/0080_auto_20211104_1347.py deleted file mode 100644 index 75210149e..000000000 --- a/apps/assets/migrations/0080_auto_20211104_1347.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.1.13 on 2021-11-04 05:47 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0079_auto_20211102_1922'), - ] - - operations = [ - migrations.AddField( - model_name='systemuser', - name='su_enabled', - field=models.BooleanField(default=False, verbose_name='User switch'), - ), - migrations.AddField( - model_name='systemuser', - name='su_from', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='su_to', to='assets.systemuser', verbose_name='Switch from'), - ), - ] diff --git a/apps/assets/migrations/0081_auto_20211105_1605.py b/apps/assets/migrations/0081_auto_20211105_1605.py deleted file mode 100644 index 08e055617..000000000 --- a/apps/assets/migrations/0081_auto_20211105_1605.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.12 on 2021-11-05 08:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0080_auto_20211104_1347'), - ] - - operations = [ - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('k8s', 'K8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0082_auto_20211209_1440.py b/apps/assets/migrations/0082_auto_20211209_1440.py deleted file mode 100644 index a0576fe13..000000000 --- a/apps/assets/migrations/0082_auto_20211209_1440.py +++ /dev/null @@ -1,74 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-09 06:40 - -from django.conf import settings -from django.db import migrations, models - - -def migrate_system_users_cmd_filters(apps, schema_editor): - system_user_model = apps.get_model("assets", "SystemUser") - cmd_filter_model = apps.get_model("assets", "CommandFilter") - su_through = system_user_model.cmd_filters.through - cf_through = cmd_filter_model.system_users.through - - su_relation_objects = su_through.objects.all() - cf_relation_objects = [ - cf_through(**{ - 'id': su_relation.id, - 'systemuser_id': su_relation.systemuser_id, - 'commandfilter_id': su_relation.commandfilter_id - }) - for su_relation in su_relation_objects - ] - cf_through.objects.bulk_create(cf_relation_objects) - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0014_auto_20211105_1605'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0081_auto_20211105_1605'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilter', - name='applications', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to='applications.Application', verbose_name='Application'), - ), - migrations.AddField( - model_name='commandfilter', - name='assets', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to='assets.Asset', verbose_name='Asset'), - ), - migrations.AddField( - model_name='commandfilter', - name='system_users', - field=models.ManyToManyField(blank=True, related_name='cmd_filters_pre', to='assets.SystemUser', verbose_name='System user'), - ), - migrations.AddField( - model_name='commandfilter', - name='users', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - migrations.AddField( - model_name='commandfilter', - name='user_groups', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to='users.UserGroup', verbose_name='User group'), - ), - migrations.AlterField( - model_name='systemuser', - name='cmd_filters', - field=models.ManyToManyField(blank=True, related_name='system_users_bak', to='assets.CommandFilter', verbose_name='Command filter'), - ), - migrations.RunPython(migrate_system_users_cmd_filters), - migrations.RemoveField( - model_name='systemuser', - name='cmd_filters', - ), - migrations.AlterField( - model_name='commandfilter', - name='system_users', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to='assets.SystemUser', verbose_name='System user'), - ), - ] diff --git a/apps/assets/migrations/0083_auto_20211215_1436.py b/apps/assets/migrations/0083_auto_20211215_1436.py deleted file mode 100644 index f3bde1ec9..000000000 --- a/apps/assets/migrations/0083_auto_20211215_1436.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-15 06:36 - -from django.db import migrations, models - -OLD_ACTION_ALLOW = 1 -NEW_ACTION_ALLOW = 9 - - -def migrate_action(apps, schema_editor): - model = apps.get_model("assets", "CommandFilterRule") - model.objects.filter(action=OLD_ACTION_ALLOW).update(action=NEW_ACTION_ALLOW) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0082_auto_20211209_1440'), - ] - - operations = [ - migrations.RunPython(migrate_action), - migrations.AlterField( - model_name='commandfilterrule', - name='action', - field=models.IntegerField(choices=[(0, 'Deny'), (9, 'Allow'), (2, 'Reconfirm')], default=0, verbose_name='Action'), - ), - ] diff --git a/apps/assets/migrations/0084_auto_20220112_1959.py b/apps/assets/migrations/0084_auto_20220112_1959.py deleted file mode 100644 index 71951bad3..000000000 --- a/apps/assets/migrations/0084_auto_20220112_1959.py +++ /dev/null @@ -1,62 +0,0 @@ -# Generated by Django 3.1.13 on 2022-01-12 11:59 - -import common.db.encoder -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0083_auto_20211215_1436'), - ] - - operations = [ - migrations.CreateModel( - name='AccountBackupPlan', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')), - ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')), - ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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)), - ('types', models.IntegerField(choices=[(255, 'All'), (1, 'Asset'), (2, 'Application')], default=255, verbose_name='Type')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('recipients', models.ManyToManyField(blank=True, related_name='recipient_escape_route_plans', to=settings.AUTH_USER_MODEL, verbose_name='Recipient')), - ], - options={ - 'verbose_name': 'Account backup plan', - 'ordering': ['name'], - 'unique_together': {('name', 'org_id')}, - }, - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('redis', 'Redis'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('k8s', 'K8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.CreateModel( - name='AccountBackupPlanExecution', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('date_start', models.DateTimeField(auto_now_add=True, verbose_name='Date start')), - ('timedelta', models.FloatField(default=0.0, null=True, verbose_name='Time')), - ('plan_snapshot', models.JSONField(blank=True, default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True, verbose_name='Account backup snapshot')), - ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')), - ('reason', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Reason')), - ('is_success', models.BooleanField(default=False, verbose_name='Is success')), - ('plan', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='execution', to='assets.accountbackupplan', verbose_name='Account backup plan')), - ], - options={ - 'verbose_name': 'Account backup execution', - }, - ), - ] diff --git a/apps/assets/migrations/0085_commandfilterrule_ignore_case.py b/apps/assets/migrations/0085_commandfilterrule_ignore_case.py deleted file mode 100644 index b1289b7c5..000000000 --- a/apps/assets/migrations/0085_commandfilterrule_ignore_case.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-08 02:57 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0084_auto_20220112_1959'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilterrule', - name='ignore_case', - field=models.BooleanField(default=True, verbose_name='Ignore case'), - ), - ] diff --git a/apps/assets/migrations/0086_auto_20220217_2135.py b/apps/assets/migrations/0086_auto_20220217_2135.py deleted file mode 100644 index fcdb9e0c8..000000000 --- a/apps/assets/migrations/0086_auto_20220217_2135.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-17 13:35 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0085_commandfilterrule_ignore_case'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['hostname'], 'permissions': [('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetsystemuser', 'Can push system user to asset')], 'verbose_name': 'Asset'}, - ), - migrations.AlterModelOptions( - name='authbook', - options={'permissions': [('view_assetaccountsecret', 'Can view asset account secret'), ('change_assetaccountsecret', 'Can change asset account secret')], 'verbose_name': 'AuthBook'}, - ), - migrations.AlterModelOptions( - name='label', - options={'verbose_name': 'Label'}, - ), - ] diff --git a/apps/assets/migrations/0087_auto_20220223_1539.py b/apps/assets/migrations/0087_auto_20220223_1539.py deleted file mode 100644 index cf707a495..000000000 --- a/apps/assets/migrations/0087_auto_20220223_1539.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-23 07:39 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0086_auto_20220217_2135'), - ] - - operations = [ - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('k8s', 'K8s')], default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/assets/migrations/0088_auto_20220303_1612.py b/apps/assets/migrations/0088_auto_20220303_1612.py deleted file mode 100644 index f0b0191e1..000000000 --- a/apps/assets/migrations/0088_auto_20220303_1612.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-03 08:12 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0087_auto_20220223_1539'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['hostname'], 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetsystemuser', 'Can push system user to asset'), ('match_asset', 'Can match asset')], 'verbose_name': 'Asset'}, - ), - migrations.AlterModelOptions( - name='node', - options={'ordering': ['parent_key', 'value'], 'permissions': [('match_node', 'Can match node')], 'verbose_name': 'Node'}, - ), - migrations.AlterModelOptions( - name='systemuser', - options={'ordering': ['name'], 'permissions': [('match_systemuser', 'Can match system user')], 'verbose_name': 'System user'}, - ), - ] diff --git a/apps/assets/migrations/0089_auto_20220310_0616.py b/apps/assets/migrations/0089_auto_20220310_0616.py deleted file mode 100644 index 1aa70d616..000000000 --- a/apps/assets/migrations/0089_auto_20220310_0616.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-09 22:16 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0088_auto_20220303_1612'), - ] - - operations = [ - migrations.AlterModelOptions( - name='authbook', - options={'permissions': [('test_authbook', 'Can test asset account connectivity'), ('view_assetaccountsecret', 'Can view asset account secret'), ('change_assetaccountsecret', 'Can change asset account secret')], 'verbose_name': 'AuthBook'}, - ), - migrations.AlterModelOptions( - name='systemuser', - options={'ordering': ['name'], 'permissions': [('match_systemuser', 'Can match system user')], 'verbose_name': 'System user'}, - ), - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['hostname'], 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetsystemuser', 'Can push system user to asset'), ('match_asset', 'Can match asset'), ('add_assettonode', 'Add asset to node'), ('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'}, - ), - migrations.AlterModelOptions( - name='gateway', - options={'permissions': [('test_gateway', 'Test gateway')], 'verbose_name': 'Gateway'}, - ), - ] diff --git a/apps/assets/migrations/0090_auto_20220412_1145.py b/apps/assets/migrations/0090_auto_20220412_1145.py deleted file mode 100644 index 3259cd37b..000000000 --- a/apps/assets/migrations/0090_auto_20220412_1145.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-12 03:45 - -from django.db import migrations, models - - -def create_internal_platform(apps, schema_editor): - model = apps.get_model("assets", "Platform") - db_alias = schema_editor.connection.alias - type_platforms = ( - ('AIX', 'Unix', None), - ) - for name, base, meta in type_platforms: - defaults = {'name': name, 'base': base, 'meta': meta, 'internal': True} - model.objects.using(db_alias).update_or_create( - name=name, defaults=defaults - ) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0089_auto_20220310_0616'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='number', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Asset number'), - ), - migrations.RunPython(create_internal_platform) - ] diff --git a/apps/assets/migrations/0091_auto_20220629_1826.py b/apps/assets/migrations/0091_auto_20220629_1826.py deleted file mode 100644 index 589dce2b2..000000000 --- a/apps/assets/migrations/0091_auto_20220629_1826.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 3.1.14 on 2022-06-29 10:26 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0090_auto_20220412_1145'), - ] - - operations = [ - migrations.AlterModelOptions( - name='authbook', - options={'permissions': [('test_authbook', 'Can test asset account connectivity'), ('view_assetaccountsecret', 'Can view asset account secret'), ('change_assetaccountsecret', 'Can change asset account secret'), ('view_assethistoryaccount', 'Can view asset history account'), ('view_assethistoryaccountsecret', 'Can view asset history account secret')], 'verbose_name': 'AuthBook'}, - ), - migrations.AlterModelOptions( - name='historicalauthbook', - options={'get_latest_by': ('history_date', 'history_id'), 'ordering': ('-history_date', '-history_id'), 'verbose_name': 'historical AuthBook', 'verbose_name_plural': 'historical AuthBooks'}, - ), - migrations.AlterField( - model_name='historicalauthbook', - name='history_date', - field=models.DateTimeField(db_index=True), - ), - ] diff --git a/apps/assets/migrations/0092_commandfilter_nodes.py b/apps/assets/migrations/0092_commandfilter_nodes.py deleted file mode 100644 index b3c1916e3..000000000 --- a/apps/assets/migrations/0092_commandfilter_nodes.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.15 on 2022-10-09 09:55 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0091_auto_20220629_1826'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilter', - name='nodes', - field=models.ManyToManyField(blank=True, related_name='cmd_filters', to='assets.Node', verbose_name='Nodes'), - ), - ] diff --git a/apps/assets/migrations/0093_auto_20220403_1627.py b/apps/assets/migrations/0093_auto_20220403_1627.py deleted file mode 100644 index 484da9740..000000000 --- a/apps/assets/migrations/0093_auto_20220403_1627.py +++ /dev/null @@ -1,193 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-02 08:27 - -import django.db -from django.db import migrations, models - -import common.db.fields - - -def migrate_to_host(apps, schema_editor): - asset_model = apps.get_model("assets", "Asset") - host_model = apps.get_model("assets", 'Host') - db_alias = schema_editor.connection.alias - - count = 0 - batch_size = 1000 - - while True: - assets = asset_model.objects.using(db_alias).all()[count:count + batch_size] - if not assets: - break - count += len(assets) - hosts = [host_model(asset_ptr=asset) for asset in assets] - host_model.objects.using(db_alias).bulk_create(hosts, ignore_conflicts=True) - - -def migrate_hardware_info(apps, *args): - asset_model = apps.get_model("assets", "Asset") - - count = 0 - batch_size = 1000 - hardware_fields = [ - 'vendor', 'model', 'sn', 'cpu_model', 'cpu_count', 'cpu_cores', - 'cpu_vcpus', 'memory', 'disk_total', 'disk_info', 'os', 'os_arch', - 'os_version', 'hostname_raw', 'number' - ] - - while True: - assets = asset_model.objects.all()[count:count + batch_size] - if not assets: - break - count += len(assets) - - updated = [] - for asset in assets: - info = {field: getattr(asset, field) for field in hardware_fields if getattr(asset, field)} - if not info: - continue - asset.info = info - updated.append(asset) - asset_model.objects.bulk_update(updated, ['info']) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0092_commandfilter_nodes'), - ] - - operations = [ - migrations.AddField( - model_name='asset', - name='info', - field=models.JSONField(blank=True, default=dict, verbose_name='Info'), - ), - migrations.RenameField( - model_name='asset', - old_name='hostname', - new_name='name', - ), - migrations.AlterField( - model_name='asset', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterModelOptions( - name='asset', - options={ - 'ordering': ['name'], - 'permissions': [ - ('refresh_assethardwareinfo', 'Can refresh asset hardware info'), - ('test_assetconnectivity', 'Can test asset connectivity'), - ('push_assetaccount', 'Can push account to asset'), - ('test_account', 'Can verify account'), ('match_asset', 'Can match asset'), - ('add_assettonode', 'Add asset to node'), - ('move_assettonode', 'Move asset to node') - ], - 'verbose_name': 'Asset' - }, - ), - migrations.RenameField( - model_name='asset', - old_name='ip', - new_name='address', - ), - migrations.AlterField( - model_name='asset', - name='address', - field=models.CharField(db_index=True, max_length=767, verbose_name='Address'), - ), - migrations.AddField( - model_name='asset', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='asset', - name='updated_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='asset', - name='created_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'), - ), - migrations.CreateModel( - name='Host', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ], - options={ - 'verbose_name': 'Host', - }, - ), - migrations.CreateModel( - name='Database', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ('db_name', models.CharField(blank=True, max_length=1024, verbose_name='Database')), - ('allow_invalid_cert', models.BooleanField(default=False, verbose_name='Allow invalid cert')), - ('ca_cert', common.db.fields.EncryptTextField(blank=True, verbose_name='CA cert')), - ('client_cert', common.db.fields.EncryptTextField(blank=True, verbose_name='Client cert')), - ('client_key', common.db.fields.EncryptTextField(blank=True, verbose_name='Client key'),), - ('use_ssl', models.BooleanField(default=False, verbose_name='Use SSL'),), - ], - options={ - 'verbose_name': 'Database', - }, - bases=('assets.asset',), - ), - migrations.CreateModel( - name='Device', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ], - options={ - 'abstract': False, - 'verbose_name': 'Device', - }, - bases=('assets.asset',), - ), - migrations.CreateModel( - name='Cloud', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ], - options={ - 'abstract': False, - 'verbose_name': 'Cloud', - }, - bases=('assets.asset',), - ), - migrations.CreateModel( - name='Web', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ('autofill', models.CharField(choices=[('no', 'Disabled'), ('basic', 'Basic'), ('script', 'Script')], - default='basic', max_length=16, verbose_name='Autofill')), - ('password_selector', - models.CharField(blank=True, default='', max_length=128, verbose_name='Password selector')), - ('submit_selector', - models.CharField(blank=True, default='', max_length=128, verbose_name='Submit selector')), - ('username_selector', - models.CharField(blank=True, default='', max_length=128, verbose_name='Username selector')), - ('script', models.JSONField(blank=True, default=list, verbose_name='Script')), - ], - options={ - 'abstract': False, - 'verbose_name': 'Web', - }, - bases=('assets.asset',), - ), - migrations.RunPython(migrate_hardware_info), - migrations.RunPython(migrate_to_host), - ] diff --git a/apps/assets/migrations/0094_auto_20220402_1736.py b/apps/assets/migrations/0094_auto_20220402_1736.py deleted file mode 100644 index daf53270b..000000000 --- a/apps/assets/migrations/0094_auto_20220402_1736.py +++ /dev/null @@ -1,69 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-02 09:36 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0093_auto_20220403_1627'), - ] - - operations = [ - migrations.RemoveField( - model_name='asset', - name='cpu_cores', - ), - migrations.RemoveField( - model_name='asset', - name='cpu_count', - ), - migrations.RemoveField( - model_name='asset', - name='cpu_model', - ), - migrations.RemoveField( - model_name='asset', - name='cpu_vcpus', - ), - migrations.RemoveField( - model_name='asset', - name='disk_info', - ), - migrations.RemoveField( - model_name='asset', - name='disk_total', - ), - migrations.RemoveField( - model_name='asset', - name='hostname_raw', - ), - migrations.RemoveField( - model_name='asset', - name='memory', - ), - migrations.RemoveField( - model_name='asset', - name='model', - ), - migrations.RemoveField( - model_name='asset', - name='os', - ), - migrations.RemoveField( - model_name='asset', - name='os_arch', - ), - migrations.RemoveField( - model_name='asset', - name='os_version', - ), - migrations.RemoveField( - model_name='asset', - name='sn', - ), - migrations.RemoveField( - model_name='asset', - name='vendor', - ), - ] diff --git a/apps/assets/migrations/0095_auto_20220407_1726.py b/apps/assets/migrations/0095_auto_20220407_1726.py deleted file mode 100644 index fa0798a20..000000000 --- a/apps/assets/migrations/0095_auto_20220407_1726.py +++ /dev/null @@ -1,51 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-07 09:26 - -from django.db import migrations, models - - -def migrate_platform_type_to_lower(apps, *args): - platform_model = apps.get_model('assets', 'Platform') - platforms = platform_model.objects.all() - for p in platforms: - p.type = p.type.lower() - p.save() - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0094_auto_20220402_1736'), - ] - - operations = [ - migrations.RenameField( - model_name='platform', - old_name='base', - new_name='type', - ), - migrations.AddField( - model_name='platform', - name='category', - field=models.CharField(default='host', max_length=32, verbose_name='Category'), - ), - migrations.AlterField( - model_name='platform', - name='type', - field=models.CharField(default='linux', max_length=32, verbose_name='Type'), - ), - migrations.AddField( - model_name='platform', - name='domain_enabled', - field=models.BooleanField(default=True, verbose_name='Domain enabled'), - ), - migrations.AddField( - model_name='platform', - name='su_enabled', - field=models.BooleanField(default=False, verbose_name='Su enabled'), - ), - migrations.AddField( - model_name='platform', - name='su_method', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Su method'), - ), - migrations.RunPython(migrate_platform_type_to_lower) - ] diff --git a/apps/assets/migrations/0096_auto_20220426_1550.py b/apps/assets/migrations/0096_auto_20220426_1550.py deleted file mode 100644 index 274a22331..000000000 --- a/apps/assets/migrations/0096_auto_20220426_1550.py +++ /dev/null @@ -1,57 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-26 07:54 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0095_auto_20220407_1726'), - ] - - operations = [ - migrations.CreateModel( - name='PlatformProtocol', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=32, verbose_name='Name')), - ('port', models.IntegerField(verbose_name='Port')), - ('setting', models.JSONField(default=dict, verbose_name='Setting')), - ('platform', - models.ForeignKey(on_delete=models.deletion.CASCADE, related_name='protocols', to='assets.platform'),), - ('default', models.BooleanField(default=True, verbose_name='Default')), - ('required', models.BooleanField(default=False, verbose_name='Required')), - ], - ), - migrations.CreateModel( - name='PlatformAutomation', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('ansible_enabled', models.BooleanField(default=False, verbose_name='Enabled')), - ('ansible_config', models.JSONField(default=dict, verbose_name='Ansible config')), - ('ping_enabled', models.BooleanField(default=False, verbose_name='Ping enabled')), - ('ping_method', models.CharField(blank=True, max_length=32, null=True, verbose_name='Ping method')), - ('gather_facts_enabled', models.BooleanField(default=False, verbose_name='Gather facts enabled')), - ('gather_facts_method', - models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method')), - ('change_secret_enabled', models.BooleanField(default=False, verbose_name='Change secret enabled')), - ('change_secret_method', - models.TextField(blank=True, max_length=32, null=True, verbose_name='Change secret method')), - ('push_account_enabled', models.BooleanField(default=False, verbose_name='Push account enabled')), - ('push_account_method', - models.TextField(blank=True, max_length=32, null=True, verbose_name='Push account method')), - ('verify_account_enabled', models.BooleanField(default=False, verbose_name='Verify account enabled')), - ('verify_account_method', - models.TextField(blank=True, max_length=32, null=True, verbose_name='Verify account method')), - ('gather_accounts_enabled', models.BooleanField(default=False, verbose_name='Gather facts enabled')), - ('gather_accounts_method', - models.TextField(blank=True, max_length=32, null=True, verbose_name='Gather facts method')), - ], - ), - migrations.AddField( - model_name='platform', - name='automation', - field=models.OneToOneField(blank=True, null=True, on_delete=models.deletion.CASCADE, - related_name='platform', to='assets.platformautomation', - verbose_name='Automation'), - ), - ] diff --git a/apps/assets/migrations/0097_auto_20220426_1558.py b/apps/assets/migrations/0097_auto_20220426_1558.py deleted file mode 100644 index 3fdf648a1..000000000 --- a/apps/assets/migrations/0097_auto_20220426_1558.py +++ /dev/null @@ -1,1243 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-26 07:58 - -import json - -from django.db import migrations - -from assets.const import AllTypes - -platforms_data_json = '''[ - { - "category": "host", - "type": "linux", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "Linux", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_posix", - "push_account_method": "push_account_posix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "linux", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "Gateway", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_posix", - "push_account_method": "push_account_posix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "unix", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "Unix", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_posix", - "push_account_method": "push_account_posix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "unix", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "macOS", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_posix", - "push_account_method": "push_account_posix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "unix", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "BSD", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_posix", - "push_account_method": "push_account_posix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "unix", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": true, - "name": "AIX", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "smart" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "posix_ping", - "gather_facts_method": "gather_facts_posix", - "gather_accounts_method": "gather_accounts_posix", - "verify_account_method": "verify_account_posix", - "change_secret_method": "change_secret_aix", - "push_account_method": "push_account_aix" - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - }, - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "required": false, - "default": false - } - ] - }, - { - "category": "host", - "type": "windows", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Windows", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_shell_type": "cmd", - "ansible_connection": "ssh" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "win_ping", - "gather_facts_method": "gather_facts_windows", - "gather_accounts_method": "gather_accounts_windows", - "verify_account_method": "verify_account_windows", - "change_secret_method": "change_secret_local_windows", - "push_account_method": "push_account_local_windows" - }, - "protocols": [ - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "required": false, - "default": false - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "host", - "type": "windows", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Windows-TLS", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_shell_type": "cmd", - "ansible_connection": "ssh" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "win_ping", - "gather_facts_method": "gather_facts_windows", - "gather_accounts_method": "gather_accounts_windows", - "verify_account_method": "verify_account_windows", - "change_secret_method": "change_secret_local_windows", - "push_account_method": "push_account_local_windows" - }, - "protocols": [ - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "tls" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "required": false, - "default": false - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "host", - "type": "windows", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Windows-RDP", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_shell_type": "cmd", - "ansible_connection": "ssh" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "win_ping", - "gather_facts_method": "gather_facts_windows", - "gather_accounts_method": "gather_accounts_windows", - "verify_account_method": "verify_account_windows", - "change_secret_method": "change_secret_local_windows", - "push_account_method": "push_account_local_windows" - }, - "protocols": [ - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "rdp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "required": false, - "default": false - }, - { - "name": "vnc", - "port": 5900, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "host", - "type": "windows", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "RemoteAppHost", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_shell_type": "cmd", - "ansible_connection": "ssh" - }, - "ping_enabled": true, - "gather_facts_enabled": true, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "win_ping", - "gather_facts_method": "gather_facts_windows", - "gather_accounts_method": "gather_accounts_windows", - "verify_account_method": "verify_account_windows", - "change_secret_method": "change_secret_local_windows", - "push_account_method": "push_account_local_windows" - }, - "protocols": [ - { - "name": "rdp", - "port": 3389, - "setting": { - "console": false, - "security": "any" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "required": true, - "default": false - } - ] - }, - { - "category": "device", - "type": "general", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "General", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "device", - "type": "general", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Cisco", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "device", - "type": "general", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Huawei", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "device", - "type": "general", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "H3C", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "ssh", - "port": 22, - "setting": { - "sftp_enabled": true, - "sftp_home": "/tmp" - }, - "primary": true, - "required": false, - "default": false - }, - { - "name": "telnet", - "port": 23, - "required": false, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "mysql", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "MySQL", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "mysql_ping", - "gather_accounts_method": "gather_accounts_mysql", - "verify_account_method": "verify_account_mysql", - "change_secret_method": "change_secret_mysql", - "push_account_method": "push_account_mysql" - }, - "protocols": [ - { - "name": "mysql", - "port": 3306, - "setting": {}, - "required": false, - "primary": true, - "default": false - } - ] - }, - { - "category": "database", - "type": "mariadb", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "MariaDB", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "mysql_ping", - "gather_accounts_method": "gather_accounts_mysql", - "verify_account_method": "verify_account_mysql", - "change_secret_method": "change_secret_mysql", - "push_account_method": "push_account_mysql" - }, - "protocols": [ - { - "name": "mariadb", - "port": 3306, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "postgresql", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "PostgreSQL", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "ping_postgresql", - "gather_accounts_method": "gather_accounts_postgresql", - "verify_account_method": "verify_account_postgresql", - "change_secret_method": "change_secret_postgresql", - "push_account_method": "push_account_postgresql" - }, - "protocols": [ - { - "name": "postgresql", - "port": 5432, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "oracle", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Oracle", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "oracle_ping", - "gather_accounts_method": "gather_accounts_oracle", - "verify_account_method": "verify_account_oracle", - "change_secret_method": "change_secret_oracle", - "push_account_method": "push_account_oracle" - }, - "protocols": [ - { - "name": "oracle", - "port": 1521, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "sqlserver", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "SQLServer", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "sqlserver_ping", - "verify_account_method": "verify_account_sqlserver", - "change_secret_method": "change_secret_sqlserver", - "push_account_method": "push_account_sqlserver" - }, - "protocols": [ - { - "name": "sqlserver", - "port": 1433, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "clickhouse", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "ClickHouse", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "clickhouse", - "port": 9000, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "mongodb", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "MongoDB", - "automation": { - "ansible_enabled": true, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": true, - "gather_facts_enabled": false, - "gather_accounts_enabled": true, - "verify_account_enabled": true, - "change_secret_enabled": true, - "push_account_enabled": true, - "ping_method": "mongodb_ping", - "gather_accounts_method": "gather_accounts_mongodb", - "verify_account_method": "verify_account_mongodb", - "change_secret_method": "change_secret_mongodb", - "push_account_method": "push_account_mongodb" - }, - "protocols": [ - { - "name": "mongodb", - "port": 27017, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - }, - { - "category": "database", - "type": "redis", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Redis", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "redis", - "port": 6379, - "required": false, - "setting": { - "auth_username": false - }, - "primary": true, - "default": false - } - ] - }, - { - "category": "database", - "type": "redis", - "internal": true, - "charset": "utf-8", - "domain_enabled": true, - "su_enabled": false, - "name": "Redis6+", - "automation": { - "ansible_enabled": false, - "ansible_config": { - "ansible_connection": "local" - }, - "ping_enabled": false, - "gather_facts_enabled": false, - "gather_accounts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false - }, - "protocols": [ - { - "name": "redis", - "port": 6379, - "required": false, - "setting": { - "auth_username": true - }, - "primary": true, - "default": false - } - ] - }, - { - "category": "web", - "type": "website", - "internal": true, - "charset": "utf-8", - "domain_enabled": false, - "su_enabled": false, - "name": "Website", - "automation": { - "ansible_enabled": false, - "ping_enabled": false, - "gather_facts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false, - "gather_accounts_enabled": false - }, - "protocols": [ - { - "name": "http", - "port": 80, - "setting": { - "username_selector": "name=username", - "password_selector": "name=password", - "submit_selector": "id=longin_button" - }, - "primary": true, - "required": false, - "default": false - } - ] - }, - { - "category": "cloud", - "type": "private", - "internal": true, - "charset": "utf-8", - "domain_enabled": false, - "su_enabled": false, - "name": "Vmware-vSphere", - "automation": { - "ansible_enabled": false, - "ansible_config": {}, - "gather_facts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false, - "gather_accounts_enabled": false - }, - "protocols": [ - { - "name": "http", - "port": 80, - "setting": { - "username_selector": "name=username", - "password_selector": "name=password", - "submit_selector": "id=longin_button" - }, - "primary": true, - "required": false, - "default": false - } - ] - }, - { - "category": "cloud", - "type": "k8s", - "internal": true, - "charset": "utf-8", - "domain_enabled": false, - "su_enabled": false, - "name": "Kubernetes", - "automation": { - "ansible_enabled": false, - "ansible_config": {}, - "gather_facts_enabled": false, - "verify_account_enabled": false, - "change_secret_enabled": false, - "push_account_enabled": false, - "gather_accounts_enabled": false - }, - "protocols": [ - { - "name": "k8s", - "port": 443, - "required": false, - "primary": true, - "default": false, - "setting": {} - } - ] - } -]''' - - -def create_internal_platforms(apps, *args): - platform_cls = apps.get_model('assets', 'Platform') - platforms_data = json.loads(platforms_data_json) - - for platform_data in platforms_data: - protocols = platform_data.pop('protocols', []) - platform_data['protocols'] = [p for p in protocols if p.pop('primary', True) is not None] - AllTypes.create_or_update_by_platform_data(platform_data, platform_cls=platform_cls) - - -def update_user_platforms(apps, *args): - platform_cls = apps.get_model('assets', 'Platform') - AllTypes.update_user_create_platforms(platform_cls) - - -def migrate_macos_platform(apps, schema_editor): - db_alias = schema_editor.connection.alias - asset_model = apps.get_model('assets', 'Asset') - platform_model = apps.get_model('assets', 'Platform') - old_macos = platform_model.objects.using(db_alias).filter( - name='MacOS', type='macos' - ).first() - new_macos = platform_model.objects.using(db_alias).filter( - name='macOS', type='unix' - ).first() - - if not old_macos or not new_macos: - return - - asset_model.objects.using(db_alias).filter( - platform=old_macos - ).update(platform=new_macos) - - platform_model.objects.using(db_alias).filter(id=old_macos.id).delete() - - -def migrate_connectivity(apps, schema_editor): - db_alias = schema_editor.connection.alias - asset_model = apps.get_model('assets', 'Asset') - asset_model.objects.using(db_alias).filter(connectivity='unknown').update(connectivity='-') - asset_model.objects.using(db_alias).filter(connectivity='failed').update(connectivity='err') - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0096_auto_20220426_1550'), - ] - - operations = [ - migrations.RunPython(create_internal_platforms), - migrations.RunPython(update_user_platforms), - migrations.RunPython(migrate_macos_platform), - migrations.RunPython(migrate_connectivity), - ] diff --git a/apps/assets/migrations/0098_auto_20220430_2126.py b/apps/assets/migrations/0098_auto_20220430_2126.py deleted file mode 100644 index 9abbea40b..000000000 --- a/apps/assets/migrations/0098_auto_20220430_2126.py +++ /dev/null @@ -1,171 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-26 07:58 -import uuid - -from django.db import migrations - -failed_apps = [] - - -def get_prop_name_id(apps, app, category): - asset_model = apps.get_model('assets', 'Asset') - _id = app.id - id_exists = asset_model.objects.filter(id=_id).exists() - if id_exists: - _id = uuid.uuid4() - name = app.name - name_exists = asset_model.objects.filter(name=name).exists() - if name_exists: - name = category + '-' + app.name - return _id, name - - -def migrate_database_to_asset(apps, *args): - node_model = apps.get_model('assets', 'Node') - app_model = apps.get_model('applications', 'Application') - db_model = apps.get_model('assets', 'Database') - platform_model = apps.get_model('assets', 'Platform') - - applications = app_model.objects.filter(category='db') - platforms = platform_model.objects.all().filter(internal=True).exclude(name='Redis6+') - platforms_map = {p.type: p for p in platforms} - print() - - for app in applications: - attrs = {'host': '', 'port': 0, 'database': ''} - _attrs = app.attrs or {} - attrs.update(_attrs) - - name = 'DB-{}'.format(app.name) - db = db_model( - id=app.id, name=name, address=attrs['host'], - protocols='{}/{}'.format(app.type, attrs['port']), - db_name=attrs['database'] or '', - platform=platforms_map[app.type], - org_id=app.org_id - ) - try: - print("\t- Create database: ", app.name) - db.save() - except: - failed_apps.append(app) - pass - - -def migrate_cloud_to_asset(apps, *args): - app_model = apps.get_model('applications', 'Application') - cloud_model = apps.get_model('assets', 'Cloud') - platform_model = apps.get_model('assets', 'Platform') - - applications = app_model.objects.filter(category='cloud') - platform = platform_model.objects.filter(type='k8s').first() - print() - - for app in applications: - attrs = app.attrs - print("\t- Create cloud: {}".format(app.name)) - name = 'Cloud-{}'.format(app.name) - cloud = cloud_model( - id=app.id, name=name, - address=attrs.get('cluster', ''), - protocols='k8s/443', platform=platform, - org_id=app.org_id, - ) - - try: - cloud.save() - except Exception as e: - failed_apps.append(cloud) - print("Error: ", e) - - -def create_app_nodes(apps, org_id): - node_model = apps.get_model('assets', 'Node') - - child_pattern = r'^[0-9]+:[0-9]+$' - node_keys = node_model.objects.filter(org_id=org_id) \ - .filter(key__regex=child_pattern) \ - .values_list('key', flat=True) - if node_keys: - node_key_split = [key.split(':') for key in node_keys] - next_value = max([int(k[1]) for k in node_key_split]) + 1 - parent_key = node_key_split[0][0] - else: - root_node = node_model.objects.filter(org_id=org_id) \ - .filter(parent_key='', key__regex=r'^[0-9]+$') \ - .exclude(key__startswith='-') \ - .first() - if not root_node: - return - parent_key = root_node.key - next_value = 0 - - next_key = '{}:{}'.format(parent_key, next_value) - name = 'Apps' - parent = node_model.objects.get(key=parent_key) - full_value = parent.full_value + '/' + name - defaults = { - 'key': next_key, 'value': name, 'parent_key': parent_key, - 'full_value': full_value, 'org_id': org_id - } - node, __ = node_model.objects.get_or_create( - defaults=defaults, value=name, org_id=org_id, - parent_key=parent_key - ) - node.parent = parent - return node - - -def migrate_to_nodes(apps, *args): - org_model = apps.get_model('orgs', 'Organization') - asset_model = apps.get_model('assets', 'Asset') - orgs = org_model.objects.all() - - # Todo: 优化一些 - for org in orgs: - node = create_app_nodes(apps, org.id) - assets = asset_model.objects.filter( - platform__category__in=['remote_app', 'database', 'cloud'], - org_id=org.id - ) - if not node: - continue - print("\t- Set node asset: ", node) - node.assets_amount = len(assets) - node.save() - node.assets.set(assets) - parent = node.parent - parent.assets_amount += len(assets) - parent.save() - - -def migrate_ori_host_to_devices(apps, *args): - device_model = apps.get_model('assets', 'Device') - asset_model = apps.get_model('assets', 'Asset') - host_model = apps.get_model('assets', 'Host') - hosts_need_migrate_to_device = host_model.objects.filter(asset_ptr__platform__category='device') - assets = asset_model.objects.filter(id__in=hosts_need_migrate_to_device.values_list('asset_ptr_id', flat=True)) - assets_map = {asset.id: asset for asset in assets} - - print("\t- Migrate ori host to device: ", len(hosts_need_migrate_to_device)) - for host in hosts_need_migrate_to_device: - asset = assets_map.get(host.asset_ptr_id) - if not asset: - continue - device = device_model(asset_ptr_id=asset.id) - device.__dict__.update(asset.__dict__) - device.save() - host.delete(keep_parents=True) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0097_auto_20220426_1558'), - ('applications', '0020_auto_20220316_2028') - ] - - operations = [ - migrations.RunPython(migrate_database_to_asset), - migrations.RunPython(migrate_cloud_to_asset), - migrations.RunPython(migrate_to_nodes), - migrations.RunPython(migrate_ori_host_to_devices), - ] diff --git a/apps/assets/migrations/0099_auto_20220711_1409.py b/apps/assets/migrations/0099_auto_20220711_1409.py deleted file mode 100644 index c0444048f..000000000 --- a/apps/assets/migrations/0099_auto_20220711_1409.py +++ /dev/null @@ -1,71 +0,0 @@ -# Generated by Django 3.2.12 on 2022-07-11 08:59 - -import time - -from django.conf import settings -from django.db import migrations, models - - -def migrate_asset_protocols(apps, schema_editor): - asset_model = apps.get_model('assets', 'Asset') - protocol_model = apps.get_model('assets', 'Protocol') - - count = 0 - bulk_size = 1000 - print("\n\tStart migrate asset protocols") - while True: - start = time.time() - assets = asset_model.objects.all()[count:count + bulk_size] - if not assets: - break - count += len(assets) - assets_protocols = [] - - for asset in assets: - old_protocols = asset._protocols or '{}/{}'.format(asset.protocol, asset.port) or 'ssh/22' - - if ',' in old_protocols: - _protocols = old_protocols.split(',') - else: - _protocols = old_protocols.split() - - for name_port in _protocols: - name_port_list = name_port.split('/') - if len(name_port_list) != 2: - continue - - name, port = name_port_list - protocol = protocol_model(**{'name': name, 'port': port, 'asset': asset}) - assets_protocols.append(protocol) - - protocol_model.objects.bulk_create(assets_protocols, ignore_conflicts=True) - print("\t - Create asset protocols: {}-{} using: {:.2f}s".format( - count - len(assets), count, time.time() - start - )) - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0098_auto_20220430_2126'), - ] - - operations = [ - migrations.RenameField( - model_name='asset', - old_name='protocols', - new_name='_protocols', - ), - migrations.CreateModel( - name='Protocol', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=32, verbose_name='Name')), - ('port', models.IntegerField(verbose_name='Port')), - ('asset', - models.ForeignKey(on_delete=models.deletion.CASCADE, related_name='protocols', to='assets.asset', - verbose_name='Asset')), - ], - ), - migrations.RunPython(migrate_asset_protocols), - ] diff --git a/apps/assets/migrations/0100_auto_20220711_1413.py b/apps/assets/migrations/0100_auto_20220711_1413.py deleted file mode 100644 index dd7e34394..000000000 --- a/apps/assets/migrations/0100_auto_20220711_1413.py +++ /dev/null @@ -1,270 +0,0 @@ -# Generated by Django 3.2.12 on 2022-07-11 06:13 - -import time -import math -from django.utils import timezone -from itertools import groupby -from django.db import migrations - - -def migrate_asset_accounts(apps, schema_editor): - auth_book_model = apps.get_model('assets', 'AuthBook') - account_model = apps.get_model('accounts', 'Account') - account_history_model = apps.get_model('accounts', 'HistoricalAccount') - - count = 0 - bulk_size = 1000 - print("\n\tStart migrate asset accounts") - while True: - start = time.time() - auth_books = auth_book_model.objects \ - .prefetch_related('systemuser') \ - .all()[count:count + bulk_size] - if not auth_books: - break - - count += len(auth_books) - # auth book 和 account 相同的属性 - same_attrs = [ - 'username', 'comment', 'date_created', 'date_updated', - 'created_by', 'asset_id', 'org_id', - ] - # 认证的属性,可能是 auth_book 的,可能是 system_user 的 - auth_attrs = ['password', 'private_key', 'token'] - all_attrs = same_attrs + auth_attrs - - accounts = [] - for auth_book in auth_books: - account_values = {'version': 1} - - system_user = auth_book.systemuser - if system_user: - # 更新一次系统用户的认证属性 - account_values.update({attr: getattr(system_user, attr, '') for attr in all_attrs}) - account_values['privileged'] = system_user.type == 'admin' \ - or system_user.username in ['root', 'Administrator'] - if system_user.su_enabled and system_user.su_from: - created_by = f'{str(system_user.id)}::{str(system_user.su_from.username)}' - else: - created_by = str(system_user.id) - account_values['created_by'] = created_by - - auth_book_auth = {attr: getattr(auth_book, attr, '') for attr in all_attrs if getattr(auth_book, attr, '')} - # 最终优先使用 auth_book 的认证属性 - account_values.update(auth_book_auth) - - auth_infos = [] - username = account_values.get('username') - if not username: - continue - - for attr in auth_attrs: - secret = account_values.pop(attr, None) - if not secret: - continue - - if attr == 'private_key': - secret_type = 'ssh_key' - name = f'{username}(ssh key)' - elif attr == 'token': - secret_type = 'token' - name = f'{username}(token)' - else: - secret_type = attr - name = username - auth_infos.append((name, secret_type, secret)) - - if not auth_infos: - auth_infos.append((username, 'password', '')) - - for name, secret_type, secret in auth_infos: - if not name: - continue - account = account_model(**account_values, name=name, secret=secret, secret_type=secret_type) - accounts.append(account) - - accounts.sort(key=lambda x: (x.name, x.asset_id, x.date_updated)) - grouped_accounts = groupby(accounts, lambda x: (x.name, x.asset_id)) - - accounts_to_add = [] - accounts_to_history = [] - for key, _accounts in grouped_accounts: - _accounts = list(_accounts) - if not _accounts: - continue - _account = _accounts[-1] - accounts_to_add.append(_account) - _account_history = [] - - for ac in _accounts: - if not ac.secret: - continue - if ac.id != _account.id and ac.secret == _account.secret: - continue - history_data = { - 'id': _account.id, - 'secret': ac.secret, - 'secret_type': ac.secret_type, - 'history_date': ac.date_updated, - 'history_type': '~', - 'history_change_reason': 'from account {}'.format(_account.name), - } - _account_history.append(account_history_model(**history_data)) - _account.version = len(_account_history) - accounts_to_history.extend(_account_history) - - account_model.objects.bulk_create(accounts_to_add, ignore_conflicts=True) - account_history_model.objects.bulk_create(accounts_to_history, ignore_conflicts=True) - print("\t - Create asset accounts: {}-{} using: {:.2f}s".format( - count - len(auth_books), count, time.time() - start - )) - print("\t - accounts: {}".format(len(accounts_to_add))) - print("\t - histories: {}".format(len(accounts_to_history))) - - -def update_asset_accounts_su_from(apps, schema_editor): - # Update accounts su_from - print("\n\tStart update asset accounts su_from field") - account_model = apps.get_model('accounts', 'Account') - platform_model = apps.get_model('assets', 'Platform') - asset_model = apps.get_model('assets', 'Asset') - platform_ids = list(platform_model.objects.filter(su_enabled=True).values_list('id', flat=True)) - - count = 0 - step_size = 1000 - count_account = 0 - while True: - start = time.time() - asset_ids = asset_model.objects \ - .filter(platform_id__in=platform_ids) \ - .values_list('id', flat=True)[count:count + step_size] - asset_ids = list(asset_ids) - if not asset_ids: - break - count += len(asset_ids) - - accounts = list(account_model.objects.filter(asset_id__in=asset_ids)) - - # {asset_id_account_username: account.id}} - asset_accounts_mapper = {} - for a in accounts: - try: - k = f'{a.asset_id}_{a.username}' - asset_accounts_mapper[k] = str(a.id) - except Exception as e: - pass - - update_accounts = [] - for a in accounts: - try: - if not a.created_by: - continue - created_by_list = a.created_by.split('::') - if len(created_by_list) != 2: - continue - su_from_username = created_by_list[1] - if not su_from_username: - continue - k = f'{a.asset_id}_{su_from_username}' - su_from_id = asset_accounts_mapper.get(k) - if not su_from_id: - continue - a.su_from_id = su_from_id - update_accounts.append(a) - except Exception as e: - pass - - count_account += len(update_accounts) - - log_msg = "\t - [{}]: Update accounts su_from: {}-{} {:.2f}s" - try: - account_model.objects.bulk_update(update_accounts, ['su_from_id']) - except Exception as e: - status = 'Failed' - else: - status = 'Success' - print(log_msg.format(status, count_account - len(update_accounts), count_account, time.time() - start)) - - -def migrate_db_accounts(apps, schema_editor): - app_perm_model = apps.get_model('perms', 'ApplicationPermission') - account_model = apps.get_model('accounts', 'Account') - perms = app_perm_model.objects.filter(category__in=['db', 'cloud']) - - same_attrs = [ - 'username', 'comment', 'date_created', 'date_updated', - 'created_by', 'org_id', - ] - auth_attrs = ['password', 'private_key', 'token'] - all_attrs = same_attrs + auth_attrs - - print("\n\tStart migrate app accounts") - - index = 0 - total = perms.count() - - for perm in perms: - index += 1 - start = time.time() - - apps = perm.applications.all() - system_users = perm.system_users.all() - accounts = [] - for s in system_users: - values = {'version': 1} - values.update({attr: getattr(s, attr, '') for attr in all_attrs}) - values['created_by'] = str(s.id) - - auth_infos = [] - username = values['username'] - for attr in auth_attrs: - secret = values.pop(attr, None) - if not secret: - continue - - if attr == 'private_key': - secret_type = 'ssh_key' - name = f'{username}(ssh key)' - elif attr == 'token': - secret_type = 'token' - name = f'{username}(token)' - else: - secret_type = attr - name = username or f'{username}(password)' - auth_infos.append((name, secret_type, secret)) - - if not auth_infos: - name = username or f'{username}(password)' - auth_infos.append((name, 'password', '')) - - for name, secret_type, secret in auth_infos: - values['name'] = name - values['secret_type'] = secret_type - values['secret'] = secret - - if not name: - continue - - for app in apps: - values['asset_id'] = str(app.id) - account = account_model(**values) - accounts.append(account) - - account_model.objects.bulk_create(accounts, ignore_conflicts=True) - - print("\t - Progress ({}/{}), Create app accounts: {} using: {:.2f}s".format( - index, total, len(accounts), time.time() - start - )) - - -class Migration(migrations.Migration): - dependencies = [ - ('accounts', '0001_initial'), - ('assets', '0099_auto_20220711_1409'), - ] - - operations = [ - migrations.RunPython(migrate_asset_accounts), - migrations.RunPython(update_asset_accounts_su_from), - migrations.RunPython(migrate_db_accounts), - ] diff --git a/apps/assets/migrations/0101_auto_20220811_1511.py b/apps/assets/migrations/0101_auto_20220811_1511.py deleted file mode 100644 index 0287a8414..000000000 --- a/apps/assets/migrations/0101_auto_20220811_1511.py +++ /dev/null @@ -1,47 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-11 07:11 -import django.db.models -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0100_auto_20220711_1413'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='platform', - field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='assets', - to='assets.platform', verbose_name='Platform'), - ), - migrations.RemoveField( - model_name='asset', - name='admin_user', - ), - migrations.RemoveField( - model_name='asset', - name='port', - ), - migrations.RemoveField( - model_name='asset', - name='protocol', - ), - migrations.RemoveField( - model_name='asset', - name='_protocols', - ), - migrations.AlterField( - model_name='systemuser', - name='protocol', - field=models.CharField(default='ssh', max_length=16, verbose_name='Protocol'), - ), - migrations.RemoveField( - model_name='asset', - name='number', - ), - migrations.RemoveField( - model_name='asset', - name='public_ip', - ), - ] diff --git a/apps/assets/migrations/0102_auto_20220816_1022.py b/apps/assets/migrations/0102_auto_20220816_1022.py deleted file mode 100644 index 922fb23e9..000000000 --- a/apps/assets/migrations/0102_auto_20220816_1022.py +++ /dev/null @@ -1,67 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-16 02:22 -import time -from django.db import migrations, models -from django.db.models import Count - - -def migrate_command_filter_to_assets(apps, schema_editor): - command_filter_model = apps.get_model('assets', 'CommandFilter') - - count = 0 - bulk_size = 1000 - print("\n\tStart migrate command filters to assets") - while True: - start = time.time() - command_filters = command_filter_model.objects.all() \ - .prefetch_related('system_users')[count:count + bulk_size] - if not command_filters: - break - count += len(command_filters) - updated = [] - for command_filter in command_filters: - command_filter.accounts = [s.username for s in command_filter.system_users.all()] - updated.append(command_filter) - command_filter_model.objects.bulk_update(updated, ['accounts']) - - print("\tCreate assets: {}-{} using: {:.2f}s".format( - count - len(command_filters), count, time.time() - start - )) - - -def migrate_command_filter_apps(apps, schema_editor): - command_filter_model = apps.get_model('assets', 'CommandFilter') - command_filters = command_filter_model.objects \ - .annotate(app_count=Count('applications')) \ - .filter(app_count__gt=0) - - for command_filter in command_filters: - app_ids = command_filter.applications.all().values_list('id', flat=True) - - try: - command_filter.assets.add(*app_ids) - except: - print("Migrate command filter apps failed: {}, skip".format(command_filter.id)) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0101_auto_20220811_1511'), - ] - - operations = [ - migrations.AddField( - model_name='commandfilter', - name='accounts', - field=models.JSONField(default=list, verbose_name='Accounts'), - ), - migrations.RunPython(migrate_command_filter_to_assets), - migrations.RemoveField( - model_name='commandfilter', - name='system_users', - ), - migrations.RunPython(migrate_command_filter_apps), - migrations.RemoveField( - model_name='commandfilter', - name='applications', - ), - ] diff --git a/apps/assets/migrations/0103_auto_20220902_1021.py b/apps/assets/migrations/0103_auto_20220902_1021.py deleted file mode 100644 index dfc731736..000000000 --- a/apps/assets/migrations/0103_auto_20220902_1021.py +++ /dev/null @@ -1,103 +0,0 @@ -# Generated by Django 3.2.13 on 2022-09-29 11:03 - -from django.db import migrations - -from assets.const.host import GATEWAY_NAME - - -def _create_account_obj(secret, secret_type, gateway, asset, account_model): - return account_model( - asset=asset, - secret=secret, - org_id=gateway.org_id, - secret_type=secret_type, - username=gateway.username, - name=f'{gateway.name}-{secret_type}-{GATEWAY_NAME.lower()}', - ) - - -def migrate_gateway_to_asset(apps, schema_editor): - db_alias = schema_editor.connection.alias - node_model = apps.get_model('assets', 'Node') - org_model = apps.get_model('orgs', 'Organization') - gateway_model = apps.get_model('assets', 'Gateway') - platform_model = apps.get_model('assets', 'Platform') - gateway_platform = platform_model.objects.using(db_alias).get(name=GATEWAY_NAME) - - print('>>> migrate gateway to asset') - asset_dict = {} - host_model = apps.get_model('assets', 'Host') - asset_model = apps.get_model('assets', 'Asset') - protocol_model = apps.get_model('assets', 'Protocol') - gateways = gateway_model.objects.all() - - org_ids = gateways.order_by('org_id').values_list('org_id', flat=True).distinct() - node_dict = {} - for org_id in org_ids: - org = org_model.objects.using(db_alias).filter(id=org_id).first() - node = node_model.objects.using(db_alias).filter( - org_id=org_id, value=org.name, full_value=f'/{org.name}' - ).first() - node_dict[org_id] = node - - for gateway in gateways: - comment = gateway.comment if gateway.comment else '' - data = { - 'comment': comment, - 'name': f'{gateway.name}-{GATEWAY_NAME.lower()}', - 'address': gateway.ip, - 'domain': gateway.domain, - 'org_id': gateway.org_id, - 'is_active': gateway.is_active, - 'platform': gateway_platform, - } - asset = asset_model.objects.using(db_alias).create(**data) - node = node_dict.get(str(gateway.org_id)) - asset.nodes.set([node]) - asset_dict[gateway.id] = asset - protocol_model.objects.using(db_alias).create(name='ssh', port=gateway.port, asset=asset) - hosts = [host_model(asset_ptr=asset) for asset in asset_dict.values()] - host_model.objects.using(db_alias).bulk_create(hosts, ignore_conflicts=True) - - print('>>> migrate gateway to account') - accounts = [] - account_model = apps.get_model('accounts', 'Account') - for gateway in gateways: - password = gateway.password - private_key = gateway.private_key - asset = asset_dict[gateway.id] - if password: - accounts.append(_create_account_obj( - password, 'password', gateway, asset, account_model - )) - - if private_key: - accounts.append(_create_account_obj( - private_key, 'ssh_key', gateway, asset, account_model - )) - account_model.objects.using(db_alias).bulk_create(accounts) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0102_auto_20220816_1022'), - ] - - operations = [ - migrations.RunPython(migrate_gateway_to_asset), - migrations.DeleteModel( - name='Gateway', - ), - migrations.CreateModel( - name='Gateway', - fields=[ - ], - options={ - 'proxy': True, - 'indexes': [], - 'constraints': [], - 'verbose_name': 'Gateway' - }, - bases=('assets.host',), - ), - ] diff --git a/apps/assets/migrations/0104_auto_20220817_1544.py b/apps/assets/migrations/0104_auto_20220817_1544.py deleted file mode 100644 index 972c34e09..000000000 --- a/apps/assets/migrations/0104_auto_20220817_1544.py +++ /dev/null @@ -1,61 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-17 07:44 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0103_auto_20220902_1021'), - ] - - operations = [ - migrations.RemoveField( - model_name='historicalauthbook', - name='asset', - ), - migrations.RemoveField( - model_name='historicalauthbook', - name='history_user', - ), - migrations.RemoveField( - model_name='historicalauthbook', - name='systemuser', - ), - migrations.RemoveField( - model_name='systemuser', - name='assets', - ), - migrations.RemoveField( - model_name='systemuser', - name='groups', - ), - migrations.RemoveField( - model_name='systemuser', - name='nodes', - ), - migrations.RemoveField( - model_name='systemuser', - name='users', - ), - migrations.AlterUniqueTogether( - name='authbook', - unique_together=None, - ), - migrations.RemoveField( - model_name='authbook', - name='asset', - ), - migrations.RemoveField( - model_name='authbook', - name='systemuser', - ), - migrations.DeleteModel( - name='Cluster', - ), - migrations.DeleteModel( - name='HistoricalAuthBook', - ), - migrations.DeleteModel( - name='AuthBook', - ), - ] diff --git a/apps/assets/migrations/0105_auto_20221220_1956.py b/apps/assets/migrations/0105_auto_20221220_1956.py deleted file mode 100644 index 196a33fb8..000000000 --- a/apps/assets/migrations/0105_auto_20221220_1956.py +++ /dev/null @@ -1,127 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0104_auto_20220817_1544'), - ] - - operations = [ - migrations.AddField( - model_name='domain', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AddField( - model_name='domain', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='domain', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='favoriteasset', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='favoriteasset', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='node', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='node', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AddField( - model_name='node', - name='date_created', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created'), - ), - migrations.AddField( - model_name='node', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='node', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='label', - name='created_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'), - ), - migrations.AddField( - model_name='label', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='label', - name='updated_by', - field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='platformprotocol', - name='default', - field=models.BooleanField(default=False, verbose_name='Default'), - ), - migrations.AlterField( - model_name='gateway', - name='date_created', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='asset', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='asset', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='domain', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='favoriteasset', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='label', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='label', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='label', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='gateway', - name='date_created', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created'), - ), - ] diff --git a/apps/assets/migrations/0106_auto_20221228_1838.py b/apps/assets/migrations/0106_auto_20221228_1838.py deleted file mode 100644 index ce7718ccd..000000000 --- a/apps/assets/migrations/0106_auto_20221228_1838.py +++ /dev/null @@ -1,80 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-28 10:38 - -import common.db.fields -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0105_auto_20221220_1956'), - ('tickets', '0025_auto_20221206_1820'), - ] - - operations = [ - migrations.RemoveField( - model_name='accountbackupplanexecution', - name='plan', - ), - migrations.AlterUniqueTogether( - name='commandfilter', - unique_together=None, - ), - migrations.RemoveField( - model_name='commandfilter', - name='assets', - ), - migrations.RemoveField( - model_name='commandfilter', - name='nodes', - ), - migrations.RemoveField( - model_name='commandfilter', - name='user_groups', - ), - migrations.RemoveField( - model_name='commandfilter', - name='users', - ), - migrations.RemoveField( - model_name='commandfilterrule', - name='filter', - ), - migrations.RemoveField( - model_name='commandfilterrule', - name='reviewers', - ), - migrations.RemoveField( - model_name='gathereduser', - name='asset', - ), - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['name'], - 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetaccount', 'Can push account to asset'), ('test_account', 'Can verify account'), ('match_asset', 'Can match asset'), ('add_assettonode', 'Add asset to node'), ('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'}, - ), - migrations.AlterUniqueTogether( - name='accountbackupplan', - unique_together=None, - ), - migrations.RemoveField( - model_name='accountbackupplan', - name='recipients', - ), - migrations.DeleteModel( - name='AccountBackupPlanExecution', - ), - migrations.DeleteModel( - name='CommandFilter', - ), - migrations.DeleteModel( - name='CommandFilterRule', - ), - migrations.DeleteModel( - name='GatheredUser', - ), - migrations.DeleteModel( - name='AccountBackupPlan', - ), - ] diff --git a/apps/assets/migrations/0107_automation.py b/apps/assets/migrations/0107_automation.py deleted file mode 100644 index e5909b104..000000000 --- a/apps/assets/migrations/0107_automation.py +++ /dev/null @@ -1,96 +0,0 @@ -# Generated by Django 3.2.16 on 2022-12-30 08:08 - -import common.db.fields -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0106_auto_20221228_1838'), - ] - - operations = [ - migrations.CreateModel( - name='BaseAutomation', - 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')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('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')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')), - ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')), - ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')), - ('accounts', models.JSONField(default=list, verbose_name='Accounts')), - ('type', models.CharField(max_length=16, verbose_name='Type')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('assets', models.ManyToManyField(blank=True, to='assets.Asset', verbose_name='Assets')), - ('nodes', models.ManyToManyField(blank=True, to='assets.Node', verbose_name='Node')), - ], - options={ - 'verbose_name': 'Automation task', - 'unique_together': {('org_id', 'name', 'type')}, - }, - ), - migrations.CreateModel( - name='AutomationExecution', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')), - ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), - ('snapshot', common.db.fields.EncryptJsonDictTextField(blank=True, default=dict, null=True, verbose_name='Automation snapshot')), - ('trigger', models.CharField(choices=[('manual', 'Manual trigger'), ('timing', 'Timing trigger')], default='manual', max_length=128, verbose_name='Trigger mode')), - ('automation', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='executions', to='assets.baseautomation', verbose_name='Automation task')), - ], - options={ - 'verbose_name': 'Automation task execution', - 'ordering': ('-date_start',), - }, - ), - migrations.CreateModel( - name='AssetBaseAutomation', - fields=[ - ], - options={ - 'verbose_name': 'Asset automation task', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.baseautomation',), - ), - migrations.CreateModel( - name='GatherFactsAutomation', - fields=[ - ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), - ], - options={ - 'verbose_name': 'Gather asset facts', - }, - bases=('assets.assetbaseautomation',), - ), - migrations.CreateModel( - name='PingAutomation', - fields=[ - ('baseautomation_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.baseautomation')), - ], - options={ - 'verbose_name': 'Ping asset', - }, - bases=('assets.assetbaseautomation',), - ), - migrations.AlterField( - model_name='automationexecution', - name='automation', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='executions', to='assets.baseautomation', verbose_name='Automation task'), - ), - ] diff --git a/apps/assets/migrations/0108_alter_platform_charset.py b/apps/assets/migrations/0108_alter_platform_charset.py deleted file mode 100644 index d413068f1..000000000 --- a/apps/assets/migrations/0108_alter_platform_charset.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-07 04:41 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0107_automation'), - ] - - operations = [ - migrations.AlterField( - model_name='platform', - name='charset', - field=models.CharField(choices=[('utf-8', 'UTF-8'), ('gbk', 'GBK')], default='utf-8', max_length=8, verbose_name='Charset'), - ), - migrations.AddField( - model_name='platform', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AddField( - model_name='platform', - name='date_created', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created'), - ), - migrations.AddField( - model_name='platform', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='platform', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='platform', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - ] diff --git a/apps/assets/migrations/0109_alter_asset_options.py b/apps/assets/migrations/0109_alter_asset_options.py deleted file mode 100644 index 9140eff74..000000000 --- a/apps/assets/migrations/0109_alter_asset_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-14 07:28 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0108_alter_platform_charset'), - ] - - operations = [ - migrations.AlterModelOptions( - name='asset', - options={'ordering': [], 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('match_asset', 'Can match asset'), ('change_assetnodes', 'Can change asset nodes')], 'verbose_name': 'Asset'}, - ), - ] diff --git a/apps/assets/migrations/0110_auto_20230315_1741.py b/apps/assets/migrations/0110_auto_20230315_1741.py deleted file mode 100644 index 2c0468d87..000000000 --- a/apps/assets/migrations/0110_auto_20230315_1741.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.2.17 on 2023-03-15 09:41 - -from django.db import migrations - - -def set_windows_platform_non_console(apps, schema_editor): - Platform = apps.get_model('assets', 'Platform') - names = ['Windows', 'Windows-RDP', 'Windows-TLS', 'RemoteAppHost'] - windows = Platform.objects.filter(name__in=names) - if not windows: - return - - for p in windows: - rdp = p.protocols.filter(name='rdp').first() - if not rdp: - continue - rdp.setting['console'] = False - rdp.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0109_alter_asset_options'), - ] - - operations = [ - migrations.RunPython(set_windows_platform_non_console) - ] diff --git a/apps/assets/migrations/0111_auto_20230321_1633.py b/apps/assets/migrations/0111_auto_20230321_1633.py deleted file mode 100644 index e9f19ea0e..000000000 --- a/apps/assets/migrations/0111_auto_20230321_1633.py +++ /dev/null @@ -1,100 +0,0 @@ -# Generated by Django 3.2.17 on 2023-03-21 08:33 - -from django.db import migrations, models - - -def migrate_platform_charset(apps, schema_editor): - platform_model = apps.get_model('assets', 'Platform') - platform_model.objects.filter(charset='utf8').update(charset='utf-8') - - -def migrate_platform_protocol_primary(apps, schema_editor): - platform_model = apps.get_model('assets', 'Platform') - platforms = platform_model.objects.all() - - for platform in platforms: - p = platform.protocols.filter(primary=True).first() - if p: - continue - p = platform.protocols.first() - if not p: - continue - p.primary = True - p.save() - - -def migrate_winrm_for_win(apps, *args): - platform_cls = apps.get_model('assets', 'Platform') - windows_name = ['Windows', 'Windows-TLS', 'Windows-RDP'] - windows = platform_cls.objects.filter(name__in=windows_name) - for platform in windows: - if platform.protocols.filter(name='winrm').exists(): - continue - data = { - 'name': 'winrm', - 'port': 5985, - 'primary': False, - 'public': False, - 'required': False, - 'default': False, - 'setting': {"use_ssl": False} - } - platform.protocols.create(**data) - - -def migrate_device_platform_automation(apps, *args): - platform_cls = apps.get_model('assets', 'Platform') - names = ['General', 'Cisco', 'H3C', 'Huawei'] - platforms = platform_cls.objects.filter(name__in=names, category='device') - - for platform in platforms: - automation = getattr(platform, 'automation', None) - if not automation: - continue - automation.ansible_config = { - "ansible_connection": "local", - "first_connect_delay": 0.5, - } - automation.ansible_enabled = True - automation.change_secret_enabled = True - automation.change_secret_method = "change_secret_by_ssh" - automation.ping_enabled = True - automation.ping_method = "ping_by_ssh" - automation.verify_account_enabled = True - automation.verify_account_method = "verify_account_by_ssh" - automation.save() - - -def migrate_web_login_button_error(apps, *args): - protocol_cls = apps.get_model('assets', 'PlatformProtocol') - protocols = protocol_cls.objects.filter(name='http') - - for protocol in protocols: - submit_selector = protocol.setting.get('submit_selector', '') - submit_selector = submit_selector.replace('id=longin_button', 'id=login_button') - protocol.setting['submit_selector'] = submit_selector - protocol.save() - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0110_auto_20230315_1741'), - ] - - operations = [ - migrations.AddField( - model_name='platformprotocol', - name='primary', - field=models.BooleanField(default=False, verbose_name='Primary'), - ), - migrations.AddField( - model_name='platformprotocol', - name='public', - field=models.BooleanField(default=True, verbose_name='Public'), - ), - migrations.RunPython(migrate_platform_charset), - migrations.RunPython(migrate_platform_protocol_primary), - migrations.RunPython(migrate_winrm_for_win), - migrations.RunPython(migrate_device_platform_automation), - migrations.RunPython(migrate_web_login_button_error), - ] diff --git a/apps/assets/migrations/0112_auto_20230404_1631.py b/apps/assets/migrations/0112_auto_20230404_1631.py deleted file mode 100644 index 72285123a..000000000 --- a/apps/assets/migrations/0112_auto_20230404_1631.py +++ /dev/null @@ -1,44 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-04 08:31 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0111_auto_20230321_1633'), - ] - - operations = [ - migrations.CreateModel( - name='Custom', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ], - options={ - 'verbose_name': 'Custom asset', - }, - bases=('assets.asset',), - ), - migrations.AddField( - model_name='platform', - name='custom_fields', - field=models.JSONField(default=list, null=True, verbose_name='Custom fields'), - ), - migrations.AddField( - model_name='asset', - name='custom_info', - field=models.JSONField(default=dict, verbose_name='Custom info'), - ), - migrations.AddField( - model_name='asset', - name='gathered_info', - field=models.JSONField(blank=True, default=dict, verbose_name='Gathered info'), - ), - migrations.RemoveField( - model_name='asset', - name='info', - ), - ] diff --git a/apps/assets/migrations/0113_auto_20230411_1917.py b/apps/assets/migrations/0113_auto_20230411_1917.py deleted file mode 100644 index ca41a30ab..000000000 --- a/apps/assets/migrations/0113_auto_20230411_1917.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-11 11:17 - -from django.db import migrations - - -def migrate_device_platform_su_method(apps, schema_editor): - platform_model = apps.get_model('assets', 'Platform') - device_map = { - 'Huawei': 'super', - 'Cisco': 'enable', - 'H3C': 'super_level', - } - platforms = platform_model.objects.filter(name__in=device_map.keys()) - print() - for platform in platforms: - print("Migrate platform su method: {}".format(platform.name)) - if platform.name not in device_map: - continue - platform.su_method = device_map[platform.name] - platform.su_enabled = True - platform.save(update_fields=['su_method', 'su_enabled']) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0112_auto_20230404_1631'), - ] - - operations = [ - migrations.RunPython(migrate_device_platform_su_method) - ] diff --git a/apps/assets/migrations/0114_baseautomation_params.py b/apps/assets/migrations/0114_baseautomation_params.py deleted file mode 100644 index b48f5b302..000000000 --- a/apps/assets/migrations/0114_baseautomation_params.py +++ /dev/null @@ -1,68 +0,0 @@ -# Generated by Django 3.2.16 on 2023-04-13 10:18 - -from django.db import migrations, models - - -def migrate_automation_push_account_params(apps, schema_editor): - platform_automation_model = apps.get_model('assets', 'PlatformAutomation') - methods_id_data_map = { - 'push_account_aix': {'sudo': '/bin/whoami', 'shell': '/bin/bash', 'home': '', 'groups': ''}, - 'push_account_posix': {'sudo': '/bin/whoami', 'shell': '/bin/bash', 'home': '', 'groups': ''}, - 'push_account_local_windows': {'groups': 'Users,Remote Desktop Users'}, - } - automation_objs = [] - for automation in platform_automation_model.objects.all(): - push_account_method = automation.push_account_method - if not push_account_method: - continue - value = methods_id_data_map.get(push_account_method) - if value is None: - continue - automation.push_account_params = value - automation_objs.append(automation) - platform_automation_model.objects.bulk_update(automation_objs, ['push_account_params']) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0113_auto_20230411_1917'), - ] - - operations = [ - migrations.AddField( - model_name='baseautomation', - name='params', - field=models.JSONField(default=dict, verbose_name='Params'), - ), - migrations.AddField( - model_name='platformautomation', - name='change_secret_params', - field=models.JSONField(default=dict, verbose_name='Change secret params'), - ), - migrations.AddField( - model_name='platformautomation', - name='gather_accounts_params', - field=models.JSONField(default=dict, verbose_name='Gather facts params'), - ), - migrations.AddField( - model_name='platformautomation', - name='gather_facts_params', - field=models.JSONField(default=dict, verbose_name='Gather facts params'), - ), - migrations.AddField( - model_name='platformautomation', - name='ping_params', - field=models.JSONField(default=dict, verbose_name='Ping params'), - ), - migrations.AddField( - model_name='platformautomation', - name='push_account_params', - field=models.JSONField(default=dict, verbose_name='Push account params'), - ), - migrations.AddField( - model_name='platformautomation', - name='verify_account_params', - field=models.JSONField(default=dict, verbose_name='Verify account params'), - ), - migrations.RunPython(migrate_automation_push_account_params), - ] diff --git a/apps/assets/migrations/0115_auto_20230417_1425.py b/apps/assets/migrations/0115_auto_20230417_1425.py deleted file mode 100644 index 34cd7ef2c..000000000 --- a/apps/assets/migrations/0115_auto_20230417_1425.py +++ /dev/null @@ -1,49 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-17 06:32 - -from django.db import migrations, models - - -def migrate_platform_automation_id(apps, *args): - platform_model = apps.get_model('assets', 'Platform') - for platform in platform_model.objects.all(): - if platform.automation: - platform._automation_id = platform.automation.id - platform.save(update_fields=['_automation_id']) - - -def migrate_automation_platform(apps, *args): - platform_model = apps.get_model('assets', 'Platform') - automation_model = apps.get_model('assets', 'PlatformAutomation') - platforms = platform_model.objects.all() - for platform in platforms: - if not platform._automation_id: - continue - automation = automation_model.objects.filter(id=platform._automation_id).first() - if not automation: - continue - automation.platform = platform - automation.save(update_fields=['platform']) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0114_baseautomation_params'), - ] - - operations = [ - migrations.AddField( - model_name='platform', - name='_automation_id', - field=models.UUIDField(editable=False, null=True), - ), - migrations.RunPython(migrate_platform_automation_id), - migrations.RemoveField(model_name='platform', name='automation'), - migrations.AddField( - model_name='platformautomation', - name='platform', - field=models.OneToOneField(null=True, on_delete=models.deletion.CASCADE, - related_name='automation', to='assets.platform'), - ), - migrations.RunPython(migrate_automation_platform), - migrations.RemoveField(model_name='platform', name='_automation_id'), - ] diff --git a/apps/assets/migrations/0116_auto_20230418_1726.py b/apps/assets/migrations/0116_auto_20230418_1726.py deleted file mode 100644 index e15a5cdc0..000000000 --- a/apps/assets/migrations/0116_auto_20230418_1726.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-18 09:26 - -from django.db import migrations - - -def update_remote_app_platform(apps, schema_editor): - platform_cls = apps.get_model('assets', 'Platform') - remote_app_host = platform_cls.objects.filter(name='RemoteAppHost').first() - if not remote_app_host: - return - - protocols = remote_app_host.protocols.all() - for protocol in protocols: - if protocol.name == 'rdp': - protocol.primary = True - protocol.save() - elif protocol.name == 'ssh': - protocol.required = True - protocol.save() - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0115_auto_20230417_1425'), - ] - - operations = [ - migrations.RunPython(update_remote_app_platform) - ] diff --git a/apps/assets/migrations/0117_alter_baseautomation_params.py b/apps/assets/migrations/0117_alter_baseautomation_params.py deleted file mode 100644 index 1fc93bdd3..000000000 --- a/apps/assets/migrations/0117_alter_baseautomation_params.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.17 on 2023-05-06 06:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0116_auto_20230418_1726'), - ] - - operations = [ - migrations.AlterField( - model_name='baseautomation', - name='params', - field=models.JSONField(default=dict, verbose_name='Parameters'), - ), - ] diff --git a/apps/assets/migrations/0118_auto_20230524_1647.py b/apps/assets/migrations/0118_auto_20230524_1647.py deleted file mode 100644 index cfe8c9f99..000000000 --- a/apps/assets/migrations/0118_auto_20230524_1647.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.2.17 on 2023-05-24 08:45 - -from django.db import migrations - - -def migrate_remote_applet_host_support_winrm(apps, *args): - platform_cls = apps.get_model('assets', 'Platform') - protocol_cls = apps.get_model('assets', 'PlatformProtocol') - applet_host_platform = platform_cls.objects.filter(name='RemoteAppHost').first() - if not applet_host_platform: - return - - protocols = applet_host_platform.protocols.all() - if not protocols.filter(name='winrm').exists(): - protocol = protocol_cls(name='winrm', port=5985, public=False, platform=applet_host_platform) - protocol.save() - applet_host_platform.protocols.add(protocol) - - ssh_protocol = protocols.filter(name='ssh').first() - if ssh_protocol: - ssh_protocol.required = False - ssh_protocol.default = True - ssh_protocol.save() - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0117_alter_baseautomation_params'), - ] - - operations = [ - migrations.RunPython(migrate_remote_applet_host_support_winrm) - ] diff --git a/apps/assets/migrations/0119_assets_add_default_node.py b/apps/assets/migrations/0119_assets_add_default_node.py deleted file mode 100644 index a281196f2..000000000 --- a/apps/assets/migrations/0119_assets_add_default_node.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-05 06:28 - -from django.db import migrations - - -# 历史问题一些资产没有关联到节点,这里将这些资产关联到默认节点 -def migrate_asset_add_default_node(apps, *args): - node_model = apps.get_model('assets', 'Node') - asset_model = apps.get_model('assets', 'Asset') - m2m_model = asset_model.nodes.through - assets = asset_model.objects.filter(nodes__isnull=True).only('id', 'org_id') - org_assets_map = {} - for asset in assets: - org_assets_map.setdefault(str(asset.org_id), []).append(str(asset.id)) - - if not org_assets_map: - return - - m2m_objs = [] - for org_id, asset_ids in org_assets_map.items(): - default_node = node_model.objects.filter(parent_key='', org_id=org_id).first() - if not default_node: - continue - m2m_objs.extend( - [ - m2m_model(node=default_node, asset_id=asset_id) - for asset_id in asset_ids - ] - ) - if not m2m_objs: - return - - m2m_model.objects.bulk_create(m2m_objs) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0118_auto_20230524_1647'), - ] - - operations = [ - migrations.RunPython(migrate_asset_add_default_node), - ] diff --git a/apps/assets/migrations/0120_auto_20230630_1613.py b/apps/assets/migrations/0120_auto_20230630_1613.py deleted file mode 100644 index a5205804b..000000000 --- a/apps/assets/migrations/0120_auto_20230630_1613.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-30 08:13 - -import django.db.models.deletion -from django.db import migrations, models - - -def add_chatgpt_platform(apps, schema_editor): - platform_cls = apps.get_model('assets', 'Platform') - automation_cls = apps.get_model('assets', 'PlatformAutomation') - platform = platform_cls.objects.create( - name='ChatGPT', internal=True, category='gpt', type='chatgpt', - domain_enabled=False, su_enabled=False, comment='ChatGPT', - created_by='System', updated_by='System', - ) - platform.protocols.create(name='chatgpt', port=443, primary=True, setting={'api_mode': 'gpt-3.5-turbo'}) - automation_cls.objects.create(ansible_enabled=False, platform=platform) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0119_assets_add_default_node'), - ] - - operations = [ - migrations.CreateModel( - name='GPT', - fields=[ - ('asset_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.asset')), - ('proxy', models.CharField(blank=True, default='', max_length=128, verbose_name='Proxy')), - ], - options={ - 'verbose_name': 'Web', - }, - bases=('assets.asset',), - ), - migrations.RunPython(add_chatgpt_platform) - ] diff --git a/apps/assets/migrations/0121_auto_20230725_1458.py b/apps/assets/migrations/0121_auto_20230725_1458.py deleted file mode 100644 index c5686d950..000000000 --- a/apps/assets/migrations/0121_auto_20230725_1458.py +++ /dev/null @@ -1,100 +0,0 @@ -# Generated by Django 4.1.10 on 2023-07-25 06:58 - -from django.db import migrations -import json - - -def migrate_platforms_sftp_protocol(apps, schema_editor): - platform_protocol_cls = apps.get_model('assets', 'PlatformProtocol') - platform_cls = apps.get_model('assets', 'Platform') - ssh_protocols = platform_protocol_cls.objects \ - .filter(name='ssh', setting__sftp_enabled=True) \ - .exclude(name__in=('Gateway', 'RemoteAppHost')) \ - .filter(platform__type='linux') - platforms_has_sftp = platform_cls.objects.filter(protocols__name='sftp') - - new_protocols = [] - print("\nPlatform add sftp protocol: ") - for protocol in ssh_protocols: - protocol_setting = protocol.setting or {} - if protocol.platform in platforms_has_sftp: - continue - - kwargs = { - 'name': 'sftp', - 'port': protocol.port, - 'primary': False, - 'required': False, - 'default': True, - 'public': True, - 'setting': { - 'sftp_home': protocol_setting.get('sftp_home', '/tmp'), - }, - 'platform': protocol.platform, - } - new_protocol = platform_protocol_cls(**kwargs) - new_protocols.append(new_protocol) - print(" - {}".format(protocol.platform.name)) - - new_protocols_dict = {(protocol.name, protocol.platform): protocol for protocol in new_protocols} - new_protocols = list(new_protocols_dict.values()) - platform_protocol_cls.objects.bulk_create(new_protocols, ignore_conflicts=True) - - -def migrate_assets_sftp_protocol(apps, schema_editor): - asset_cls = apps.get_model('assets', 'Asset') - platform_cls = apps.get_model('assets', 'Platform') - protocol_cls = apps.get_model('assets', 'Protocol') - sftp_platforms = list(platform_cls.objects.filter(protocols__name='sftp').values_list('id')) - - count = 0 - print("\nAsset add sftp protocol: ") - asset_ids = list(asset_cls.objects\ - .filter(platform__in=sftp_platforms)\ - .exclude(protocols__name='sftp')\ - .distinct()\ - .values_list('id', flat=True)) - while True: - _asset_ids = asset_ids[count:count + 1000] - if not _asset_ids: - break - count += 1000 - - new_protocols = [] - ssh_protocols = protocol_cls.objects.filter(name='ssh', asset_id__in=_asset_ids).distinct() - ssh_protocols_map = {protocol.asset_id: protocol for protocol in ssh_protocols} - for asset_id, protocol in ssh_protocols_map.items(): - new_protocols.append(protocol_cls(name='sftp', port=protocol.port, asset_id=asset_id)) - protocol_cls.objects.bulk_create(new_protocols, ignore_conflicts=True) - print(" - Add {}".format(len(new_protocols))) - - -def migrate_telnet_regex(apps, schema_editor): - setting_cls = apps.get_model('settings', 'Setting') - setting = setting_cls.objects.filter(name='TERMINAL_TELNET_REGEX').first() - if not setting: - print("Not found telnet regex setting, skip") - return - try: - value = json.loads(setting.value) - except Exception: - print("Invalid telnet regex setting, skip") - return - platform_protocol_cls = apps.get_model('assets', 'PlatformProtocol') - telnets = platform_protocol_cls.objects.filter(name='telnet') - if telnets.count() > 0: - telnets.update(setting={'success_prompt': value}) - print("Migrate telnet regex setting success: ", telnets.count()) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0120_auto_20230630_1613'), - ] - - operations = [ - migrations.RunPython(migrate_platforms_sftp_protocol), - migrations.RunPython(migrate_assets_sftp_protocol), - migrations.RunPython(migrate_telnet_regex), - ] diff --git a/apps/assets/migrations/0122_auto_20230803_1553.py b/apps/assets/migrations/0122_auto_20230803_1553.py deleted file mode 100644 index 4f3071153..000000000 --- a/apps/assets/migrations/0122_auto_20230803_1553.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 4.1.10 on 2023-08-03 07:53 - -from django.db import migrations - - -def migrate_web_setting_safe_mode(apps, schema_editor): - platform_protocol_cls = apps.get_model('assets', 'PlatformProtocol') - protocols = platform_protocol_cls.objects.filter(name='http') - for protocol in protocols: - setting = protocol.setting or {} - setting['safe_mode'] = False - protocol.setting = setting - protocol.save(update_fields=['setting']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0121_auto_20230725_1458'), - ] - - operations = [ - migrations.RunPython(migrate_web_setting_safe_mode), - ] diff --git a/apps/assets/migrations/0123_device_automation_ansible_enabled.py b/apps/assets/migrations/0123_device_automation_ansible_enabled.py deleted file mode 100644 index 3ef3a4c33..000000000 --- a/apps/assets/migrations/0123_device_automation_ansible_enabled.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-13 10:59 - -from django.db import migrations - - -def migrate_device_automation_ansible_enabled(apps, *args): - platform_model = apps.get_model('assets', 'Platform') - automation_model = apps.get_model('assets', 'PlatformAutomation') - ids = platform_model.objects.filter(category='device').values_list('id', flat=True) - automation_model.objects.filter(platform_id__in=ids).update(ansible_enabled=True) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0122_auto_20230803_1553'), - ] - - operations = [ - migrations.RunPython(migrate_device_automation_ansible_enabled) - ] diff --git a/apps/assets/migrations/0124_auto_20231007_1437.py b/apps/assets/migrations/0124_auto_20231007_1437.py deleted file mode 100644 index 5a004c93d..000000000 --- a/apps/assets/migrations/0124_auto_20231007_1437.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-07 06:37 - -from django.db import migrations - - -def add_db2_platform(apps, schema_editor): - platform_cls = apps.get_model('assets', 'Platform') - automation_cls = apps.get_model('assets', 'PlatformAutomation') - platform, _ = platform_cls.objects.update_or_create( - name='DB2', defaults={ - 'name': 'DB2', 'category': 'database', - 'internal': True, 'type': 'db2', - 'domain_enabled': True, 'su_enabled': False, - 'su_method': None, 'comment': 'DB2', 'created_by': 'System', - 'updated_by': 'System', 'custom_fields': [] - } - ) - platform.protocols.update_or_create(name='db2', defaults={ - 'name': 'db2', 'port': 50000, 'primary': True, 'setting': {} - }) - automation_cls.objects.update_or_create(platform=platform, defaults={'ansible_enabled': False}) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0123_device_automation_ansible_enabled'), - ] - - operations = [ - migrations.RunPython(add_db2_platform) - ] diff --git a/apps/assets/migrations/0125_auto_20231011_1053.py b/apps/assets/migrations/0125_auto_20231011_1053.py deleted file mode 100644 index 11161c909..000000000 --- a/apps/assets/migrations/0125_auto_20231011_1053.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-11 02:53 - -from django.db import migrations - - -def change_windows_ping_method(apps, schema_editor): - platform_automation_cls = apps.get_model('assets', 'PlatformAutomation') - automations = platform_automation_cls.objects.filter(platform__name__in=['Windows', 'Windows2016']) - automations.update(ping_method='ping_by_rdp') - automations.update(verify_account_method='verify_account_by_rdp') - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0124_auto_20231007_1437'), - ] - - operations = [ - migrations.RunPython(change_windows_ping_method) - ] diff --git a/apps/assets/migrations/0126_remove_asset_labels.py b/apps/assets/migrations/0126_remove_asset_labels.py deleted file mode 100644 index 44590dc4c..000000000 --- a/apps/assets/migrations/0126_remove_asset_labels.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-22 07:33 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0125_auto_20231011_1053'), - ('labels', '0002_auto_20231103_1659'), - ] - - operations = [ - migrations.RemoveField( - model_name='asset', - name='labels', - ), - ] diff --git a/apps/assets/migrations/0127_automation_remove_account.py b/apps/assets/migrations/0127_automation_remove_account.py deleted file mode 100644 index e0746326f..000000000 --- a/apps/assets/migrations/0127_automation_remove_account.py +++ /dev/null @@ -1,55 +0,0 @@ -# Generated by Django 4.1.10 on 2023-12-05 10:03 -from functools import reduce - -from django.db import migrations, models -from django.db.models import F - - -def migrate_automation_ansible_remove_account(apps, *args): - automation_model = apps.get_model('assets', 'PlatformAutomation') - automation_map = { - ('oracle',): 'remove_account_oracle', - ('windows',): 'remove_account_windows', - ('mongodb',): 'remove_account_mongodb', - ('linux', 'unix'): 'remove_account_posix', - ('sqlserver',): 'remove_account_sqlserver', - ('mysql', 'mariadb'): 'remove_account_mysql', - ('postgresql',): 'remove_account_postgresql', - } - - update_objs = [] - types = list(reduce(lambda x, y: x + y, automation_map.keys())) - qs = automation_model.objects.filter(platform__type__in=types).annotate(tp=F('platform__type')) - for automation in qs: - for types, method in automation_map.items(): - if automation.tp in types: - automation.remove_account_enabled = True - automation.remove_account_method = method - break - update_objs.append(automation) - automation_model.objects.bulk_update(update_objs, ['remove_account_enabled', 'remove_account_method']) - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0126_remove_asset_labels'), - ] - - operations = [ - migrations.AddField( - model_name='platformautomation', - name='remove_account_enabled', - field=models.BooleanField(default=False, verbose_name='Remove account enabled'), - ), - migrations.AddField( - model_name='platformautomation', - name='remove_account_method', - field=models.TextField(blank=True, max_length=32, null=True, verbose_name='Remove account method'), - ), - migrations.AddField( - model_name='platformautomation', - name='remove_account_params', - field=models.JSONField(default=dict, verbose_name='Remove account params'), - ), - migrations.RunPython(migrate_automation_ansible_remove_account) - ] diff --git a/apps/assets/models/__init__.py b/apps/assets/models/__init__.py index 5eeaf2626..74bb94517 100644 --- a/apps/assets/models/__init__.py +++ b/apps/assets/models/__init__.py @@ -2,13 +2,8 @@ from .base import * from .platform import * from .asset import * from .label import Label -from .group import * from .gateway import * from .domain import * from .node import * from .favorite_asset import * from .automations import * -# 废弃以下 -# from ._authbook import * -# from .cmd_filter import * -from ._user import * diff --git a/apps/assets/models/_user.py b/apps/assets/models/_user.py deleted file mode 100644 index 019147456..000000000 --- a/apps/assets/models/_user.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# - -import logging -import uuid -from common.db import fields - -from django.db import models -from django.utils.translation import gettext_lazy as _ -from django.core.validators import MinValueValidator, MaxValueValidator - -from orgs.mixins.models import OrgModelMixin - - -__all__ = ['SystemUser'] -logger = logging.getLogger(__name__) - - -class OldBaseUser(models.Model): - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField(max_length=128, verbose_name=_('Name')) - username = models.CharField(max_length=128, blank=True, verbose_name=_('Username'), db_index=True) - password = fields.EncryptCharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) - private_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH private key')) - public_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH public key')) - comment = models.TextField(blank=True, verbose_name=_('Comment')) - date_created = models.DateTimeField(auto_now_add=True, verbose_name=_("Date created")) - date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated")) - created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by')) - - class Meta: - abstract = True - - -class SystemUser(OrgModelMixin, OldBaseUser): - LOGIN_AUTO = 'auto' - LOGIN_MANUAL = 'manual' - LOGIN_MODE_CHOICES = ( - (LOGIN_AUTO, _('Automatic managed')), - (LOGIN_MANUAL, _('Manually input')) - ) - - class Type(models.TextChoices): - common = 'common', _('Common user') - admin = 'admin', _('Admin user') - - token = models.TextField(default='', verbose_name=_('Token')) - username_same_with_user = models.BooleanField(default=False, verbose_name=_("Username same with user")) - type = models.CharField(max_length=16, choices=Type.choices, default=Type.common, verbose_name=_('Type')) - priority = models.IntegerField(default=81, verbose_name=_("Priority"), help_text=_("1-100, the lower the value will be match first"), validators=[MinValueValidator(1), MaxValueValidator(100)]) - protocol = models.CharField(max_length=16, default='ssh', verbose_name=_('Protocol')) - auto_push = models.BooleanField(default=True, verbose_name=_('Auto push')) - sudo = models.TextField(default='/bin/whoami', verbose_name=_('Sudo')) - shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell')) - login_mode = models.CharField(choices=LOGIN_MODE_CHOICES, default=LOGIN_AUTO, max_length=10, verbose_name=_('Login mode')) - sftp_root = models.CharField(default='tmp', max_length=128, verbose_name=_("SFTP Root")) - home = models.CharField(max_length=4096, default='', verbose_name=_('Home'), blank=True) - system_groups = models.CharField(default='', max_length=4096, verbose_name=_('System groups'), blank=True) - ad_domain = models.CharField(default='', max_length=256) - # linux su 命令 (switch user) - su_enabled = models.BooleanField(default=False, verbose_name=_('User switch')) - su_from = models.ForeignKey('self', on_delete=models.SET_NULL, related_name='su_to', null=True, verbose_name=_("Switch from")) - privileged = None - - class Meta: - ordering = ['name'] - unique_together = [('name', 'org_id')] - verbose_name = _("System user") - permissions = [ - ('match_systemuser', _('Can match system user')), - ] - - -# Deprecated: 准备废弃 -class AdminUser(OrgModelMixin, OldBaseUser): - """ - A privileged user that ansible can use it to push system user and so on - """ - BECOME_METHOD_CHOICES = ( - ('sudo', 'sudo'), - ('su', 'su'), - ) - become = models.BooleanField(default=True) - become_method = models.CharField(choices=BECOME_METHOD_CHOICES, default='sudo', max_length=4) - become_user = models.CharField(default='root', max_length=64) - _become_pass = models.CharField(default='', blank=True, max_length=128) - - def __str__(self): - return self.name - - class Meta: - ordering = ['name'] - unique_together = [('name', 'org_id')] - verbose_name = _("Admin user") \ No newline at end of file diff --git a/apps/assets/models/group.py b/apps/assets/models/group.py deleted file mode 100644 index ad3545a1e..000000000 --- a/apps/assets/models/group.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# - -from __future__ import unicode_literals - -import uuid - -from django.db import models -from django.utils.translation import gettext_lazy as _ - -__all__ = ['AssetGroup'] - - -class AssetGroup(models.Model): - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField(max_length=64, unique=True, verbose_name=_('Name')) - created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by')) - date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date created')) - comment = models.TextField(blank=True, verbose_name=_('Comment')) - - def __str__(self): - return self.name - - class Meta: - ordering = ['name'] - verbose_name = _("Asset group") - - @classmethod - def initial(cls): - asset_group = cls(name=_('Default'), comment=_('Default asset group')) - asset_group.save() diff --git a/apps/audits/migrations/0001_initial.py b/apps/audits/migrations/0001_initial.py index 0545c51d6..302358ff1 100644 --- a/apps/audits/migrations/0001_initial.py +++ b/apps/audits/migrations/0001_initial.py @@ -1,8 +1,8 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-06 04:30 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 +import common.db.encoder from django.db import migrations, models +import django.utils.timezone import uuid @@ -14,18 +14,110 @@ class Migration(migrations.Migration): ] operations = [ + migrations.CreateModel( + name='ActivityLog', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('type', models.CharField(choices=[('O', 'Operate log'), ('S', 'Session log'), ('L', 'Login log'), ('T', 'Task')], default=None, max_length=2, null=True, verbose_name='Activity type')), + ('resource_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Resource')), + ('datetime', models.DateTimeField(auto_now=True, db_index=True, verbose_name='Datetime')), + ('detail', models.TextField(blank=True, default='', verbose_name='Detail')), + ('detail_id', models.CharField(default=None, max_length=36, null=True, verbose_name='Detail ID')), + ], + options={ + 'verbose_name': 'Activity log', + 'ordering': ('-datetime',), + }, + ), migrations.CreateModel( name='FTPLog', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('user', models.CharField(max_length=128, verbose_name='User')), + ('remote_addr', models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr')), + ('asset', models.CharField(max_length=1024, verbose_name='Asset')), + ('account', models.CharField(max_length=128, verbose_name='Account')), + ('operate', models.CharField(choices=[('mkdir', 'Mkdir'), ('rmdir', 'Rmdir'), ('delete', 'Delete'), ('upload', 'Upload'), ('rename', 'Rename'), ('symlink', 'Symlink'), ('download', 'Download'), ('rename_dir', 'Rename dir')], max_length=16, verbose_name='Operate')), + ('filename', models.CharField(max_length=1024, verbose_name='Filename')), + ('is_success', models.BooleanField(default=True, verbose_name='Success')), + ('date_start', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Date start')), + ('has_file', models.BooleanField(default=False, verbose_name='File')), + ('session', models.CharField(default=uuid.uuid4, max_length=36, verbose_name='Session')), + ], + options={ + 'verbose_name': 'File transfer log', + }, + ), + migrations.CreateModel( + name='OperateLog', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('user', models.CharField(max_length=128, verbose_name='User')), + ('action', models.CharField(choices=[('view', 'View'), ('update', 'Update'), ('delete', 'Delete'), ('create', 'Create'), ('download', 'Download'), ('connect', 'Connect'), ('login', 'Login'), ('change_password', 'Change password'), ('accept', 'Accept'), ('review', 'Review'), ('notice', 'Notifications'), ('reject', 'Reject'), ('approve', 'Approve'), ('close', 'Close')], max_length=16, verbose_name='Action')), + ('resource_type', models.CharField(max_length=64, verbose_name='Resource Type')), + ('resource', models.CharField(max_length=128, verbose_name='Resource')), + ('resource_id', models.CharField(blank=True, db_index=True, default='', max_length=128, verbose_name='Resource')), + ('remote_addr', models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr')), + ('datetime', models.DateTimeField(auto_now=True, db_index=True, verbose_name='Datetime')), + ('diff', models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True)), + ], + options={ + 'verbose_name': 'Operate log', + 'ordering': ('-datetime',), + }, + ), + migrations.CreateModel( + name='PasswordChangeLog', fields=[ ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('user', models.CharField(max_length=128, verbose_name='User')), - ('remote_addr', models.CharField(blank=True, max_length=15, null=True, verbose_name='Remote addr')), - ('asset', models.CharField(max_length=1024, verbose_name='Asset')), - ('system_user', models.CharField(max_length=128, verbose_name='System user')), - ('operate', models.CharField(max_length=16, verbose_name='Operate')), - ('filename', models.CharField(max_length=1024, verbose_name='Filename')), - ('is_success', models.BooleanField(default=True, verbose_name='Success')), - ('date_start', models.DateTimeField(auto_now_add=True)), + ('change_by', models.CharField(max_length=128, verbose_name='Change by')), + ('remote_addr', models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr')), + ('datetime', models.DateTimeField(auto_now=True, verbose_name='Datetime')), ], + options={ + 'verbose_name': 'Password change log', + }, + ), + migrations.CreateModel( + name='UserLoginLog', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('username', models.CharField(max_length=128, verbose_name='Username')), + ('type', models.CharField(choices=[('W', 'Web'), ('T', 'Terminal'), ('U', 'Unknown')], max_length=2, verbose_name='Login type')), + ('ip', models.GenericIPAddressField(verbose_name='Login IP')), + ('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')), + ('mfa', models.SmallIntegerField(choices=[(0, 'Disabled'), (1, 'Enabled'), (2, '-')], default=2, verbose_name='MFA')), + ('reason', models.CharField(blank=True, default='', max_length=128, verbose_name='Reason')), + ('status', models.BooleanField(choices=[(1, 'Success'), (0, 'Failed')], default=1, verbose_name='Status')), + ('datetime', models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Login Date')), + ('backend', models.CharField(default='', max_length=32, verbose_name='Authentication backend')), + ], + options={ + 'verbose_name': 'User login log', + 'ordering': ['-datetime', 'username'], + }, + ), + migrations.CreateModel( + name='UserSession', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('ip', models.GenericIPAddressField(verbose_name='Login IP')), + ('key', models.CharField(max_length=128, verbose_name='Session key')), + ('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')), + ('type', models.CharField(choices=[('W', 'Web'), ('T', 'Terminal'), ('U', 'Unknown')], max_length=2, verbose_name='Login type')), + ('backend', models.CharField(default='', max_length=32, verbose_name='Authentication backend')), + ('date_created', models.DateTimeField(blank=True, null=True, verbose_name='Date created')), + ], + options={ + 'verbose_name': 'User session', + 'ordering': ['-date_created'], + 'permissions': [('offline_usersession', 'Offline user session')], + }, ), ] diff --git a/apps/audits/migrations/0002_ftplog_org_id.py b/apps/audits/migrations/0002_ftplog_org_id.py index 0c45da926..e571a26a3 100644 --- a/apps/audits/migrations/0002_ftplog_org_id.py +++ b/apps/audits/migrations/0002_ftplog_org_id.py @@ -1,18 +1,28 @@ -# Generated by Django 2.0.7 on 2018-08-07 03:16 +# Generated by Django 4.1.13 on 2024-05-09 03:16 -from django.db import migrations, models +from django.db import migrations class Migration(migrations.Migration): + initial = True + dependencies = [ + ('ops', '0001_initial'), ('audits', '0001_initial'), ] operations = [ - migrations.AddField( - model_name='ftplog', - name='org_id', - field=models.CharField(blank=True, db_index=True, default=None, max_length=36, null=True), + migrations.CreateModel( + name='JobLog', + fields=[ + ], + options={ + 'verbose_name': 'Job audit log', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('ops.jobexecution',), ), ] diff --git a/apps/audits/migrations/0003_auto_20180816_1652.py b/apps/audits/migrations/0003_auto_20180816_1652.py index fe5cd806d..b3908a2e4 100644 --- a/apps/audits/migrations/0003_auto_20180816_1652.py +++ b/apps/audits/migrations/0003_auto_20180816_1652.py @@ -1,18 +1,23 @@ -# Generated by Django 2.0.7 on 2018-08-16 08:52 +# Generated by Django 4.1.13 on 2024-05-09 03:16 +from django.conf import settings from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): + initial = True + dependencies = [ ('audits', '0002_ftplog_org_id'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.AlterField( - model_name='ftplog', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), + migrations.AddField( + model_name='usersession', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sessions', to=settings.AUTH_USER_MODEL, verbose_name='User'), ), ] diff --git a/apps/audits/migrations/0004_operatelog_passwordchangelog_userloginlog.py b/apps/audits/migrations/0004_operatelog_passwordchangelog_userloginlog.py deleted file mode 100644 index a6002abca..000000000 --- a/apps/audits/migrations/0004_operatelog_passwordchangelog_userloginlog.py +++ /dev/null @@ -1,41 +0,0 @@ -# Generated by Django 2.1 on 2018-09-03 03:32 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0014_auto_20180816_1652'), - ('audits', '0003_auto_20180816_1652'), - ] - - operations = [ - migrations.CreateModel( - name='OperateLog', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('user', models.CharField(max_length=128, verbose_name='User')), - ('action', models.CharField(choices=[('create', 'Create'), ('update', 'Update'), ('delete', 'Delete')], max_length=16, verbose_name='Action')), - ('resource_type', models.CharField(max_length=64, verbose_name='Resource Type')), - ('resource', models.CharField(max_length=128, verbose_name='Resource')), - ('remote_addr', models.CharField(blank=True, max_length=15, null=True, verbose_name='Remote addr')), - ('datetime', models.DateTimeField(auto_now=True)), - ], - options={ - 'abstract': False, - }, - ), - migrations.CreateModel( - name='PasswordChangeLog', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('user', models.CharField(max_length=128, verbose_name='User')), - ('change_by', models.CharField(max_length=128, verbose_name='Change by')), - ('remote_addr', models.CharField(blank=True, max_length=15, null=True, verbose_name='Remote addr')), - ('datetime', models.DateTimeField(auto_now=True)), - ], - ), - ] diff --git a/apps/audits/migrations/0005_auto_20190228_1715.py b/apps/audits/migrations/0005_auto_20190228_1715.py deleted file mode 100644 index 910644526..000000000 --- a/apps/audits/migrations/0005_auto_20190228_1715.py +++ /dev/null @@ -1,55 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-28 09:15 - -import uuid - -import django.utils.timezone -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('audits', '0004_operatelog_passwordchangelog_userloginlog'), - ('users', '0019_auto_20190304_1459'), - ] - state_operations = [ - migrations.CreateModel( - name='UserLoginLog', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, - serialize=False)), - ('username', - models.CharField(max_length=128, verbose_name='Username')), - ('type', - models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')], - max_length=2, verbose_name='Login type')), - ('ip', models.GenericIPAddressField(verbose_name='Login IP')), - ('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')), - ('mfa', models.SmallIntegerField( - choices=[(0, 'Disabled'), (1, 'Enabled'), (2, '-')], - default=2, verbose_name='MFA')), - ('reason', models.SmallIntegerField( - choices=[(0, '-'), (1, 'Username/password check failed'), - (2, 'MFA authentication failed'), - (3, 'Username does not exist'), - (4, 'Password expired')], default=0, - verbose_name='Reason')), - ('status', models.BooleanField( - choices=[(True, 'Success'), (False, 'Failed')], - default=True, max_length=2, verbose_name='Status')), - ('datetime', - models.DateTimeField(default=django.utils.timezone.now, - verbose_name='Login Date')), - ], - options={ - 'ordering': ['-datetime', 'username'], - }, - ), - ] - - operations = [ - migrations.SeparateDatabaseAndState(state_operations=state_operations) - ] diff --git a/apps/audits/migrations/0006_auto_20190726_1753.py b/apps/audits/migrations/0006_auto_20190726_1753.py deleted file mode 100644 index beb382c31..000000000 --- a/apps/audits/migrations/0006_auto_20190726_1753.py +++ /dev/null @@ -1,35 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-26 09:53 - -from django.db import migrations, models - - -def migrate_loginlog_reason_to_str(apps, schema_editor): - db_alias = schema_editor.connection.alias - - reason_map = { - "0": "", - "1": 'Username/password check failed', - "2": 'MFA authentication failed', - "3": "Username does not exist", - "4": "Password expired", - } - - model = apps.get_model("audits", "UserLoginLog") - for k, v in reason_map.items(): - model.objects.using(db_alias).filter(reason=k).update(reason=v) - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0005_auto_20190228_1715'), - ] - - operations = [ - migrations.AlterField( - model_name='userloginlog', - name='reason', - field=models.CharField(blank=True, default='', max_length=128, verbose_name='Reason'), - ), - migrations.RunPython(migrate_loginlog_reason_to_str), - ] diff --git a/apps/audits/migrations/0007_auto_20191202_1010.py b/apps/audits/migrations/0007_auto_20191202_1010.py deleted file mode 100644 index 3c355ff69..000000000 --- a/apps/audits/migrations/0007_auto_20191202_1010.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-02 02:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0006_auto_20190726_1753'), - ] - - operations = [ - migrations.AlterField( - model_name='ftplog', - name='remote_addr', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr'), - ), - migrations.AlterField( - model_name='operatelog', - name='remote_addr', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr'), - ), - migrations.AlterField( - model_name='passwordchangelog', - name='remote_addr', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr'), - ), - ] diff --git a/apps/audits/migrations/0008_auto_20200508_2105.py b/apps/audits/migrations/0008_auto_20200508_2105.py deleted file mode 100644 index bde6687ba..000000000 --- a/apps/audits/migrations/0008_auto_20200508_2105.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.2.10 on 2020-05-08 13:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0007_auto_20191202_1010'), - ] - - operations = [ - migrations.AlterField( - model_name='ftplog', - name='date_start', - field=models.DateTimeField(auto_now_add=True, verbose_name='Date start'), - ), - migrations.AlterField( - model_name='operatelog', - name='datetime', - field=models.DateTimeField(auto_now=True, verbose_name='Datetime'), - ), - migrations.AlterField( - model_name='passwordchangelog', - name='datetime', - field=models.DateTimeField(auto_now=True, verbose_name='Datetime'), - ), - ] diff --git a/apps/audits/migrations/0009_auto_20200624_1654.py b/apps/audits/migrations/0009_auto_20200624_1654.py deleted file mode 100644 index 6630558cf..000000000 --- a/apps/audits/migrations/0009_auto_20200624_1654.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-06-24 08:54 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0008_auto_20200508_2105'), - ] - - operations = [ - migrations.AlterField( - model_name='ftplog', - name='operate', - field=models.CharField(choices=[('Delete', 'Delete'), ('Upload', 'Upload'), ('Download', 'Download'), ('Rmdir', 'Rmdir'), ('Rename', 'Rename'), ('Mkdir', 'Mkdir'), ('Symlink', 'Symlink')], max_length=16, verbose_name='Operate'), - ), - ] diff --git a/apps/audits/migrations/0010_auto_20200811_1122.py b/apps/audits/migrations/0010_auto_20200811_1122.py deleted file mode 100644 index f274bf815..000000000 --- a/apps/audits/migrations/0010_auto_20200811_1122.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-11 03:22 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0009_auto_20200624_1654'), - ] - - operations = [ - migrations.AlterField( - model_name='operatelog', - name='datetime', - field=models.DateTimeField(auto_now=True, db_index=True, verbose_name='Datetime'), - ), - ] diff --git a/apps/audits/migrations/0011_userloginlog_backend.py b/apps/audits/migrations/0011_userloginlog_backend.py deleted file mode 100644 index b9c4c7890..000000000 --- a/apps/audits/migrations/0011_userloginlog_backend.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1 on 2020-12-09 03:03 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('audits', '0010_auto_20200811_1122'), - ] - - operations = [ - migrations.AddField( - model_name='userloginlog', - name='backend', - field=models.CharField(default='', max_length=32, verbose_name='Auth backend'), - ), - ] diff --git a/apps/audits/migrations/0012_auto_20210414_1443.py b/apps/audits/migrations/0012_auto_20210414_1443.py deleted file mode 100644 index 39a8ac52c..000000000 --- a/apps/audits/migrations/0012_auto_20210414_1443.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2021-04-14 06:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0011_userloginlog_backend'), - ] - - operations = [ - migrations.AlterField( - model_name='userloginlog', - name='type', - field=models.CharField(choices=[('W', 'Web'), ('T', 'Terminal'), ('U', 'Unknown')], max_length=2, verbose_name='Login type'), - ), - ] diff --git a/apps/audits/migrations/0013_auto_20211130_1037.py b/apps/audits/migrations/0013_auto_20211130_1037.py deleted file mode 100644 index 15fa2a382..000000000 --- a/apps/audits/migrations/0013_auto_20211130_1037.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.1.13 on 2021-11-30 02:37 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0012_auto_20210414_1443'), - ] - - operations = [ - migrations.AlterModelOptions( - name='ftplog', - options={'verbose_name': 'File transfer log'}, - ), - migrations.AlterModelOptions( - name='operatelog', - options={'verbose_name': 'Operate log'}, - ), - migrations.AlterModelOptions( - name='passwordchangelog', - options={'verbose_name': 'Password change log'}, - ), - migrations.AlterModelOptions( - name='userloginlog', - options={'ordering': ['-datetime', 'username'], 'verbose_name': 'User login log'}, - ), - ] diff --git a/apps/audits/migrations/0014_auto_20220505_1902.py b/apps/audits/migrations/0014_auto_20220505_1902.py deleted file mode 100644 index 8c483560c..000000000 --- a/apps/audits/migrations/0014_auto_20220505_1902.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.14 on 2022-05-05 11:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0013_auto_20211130_1037'), - ] - - operations = [ - migrations.AlterField( - model_name='operatelog', - name='action', - field=models.CharField(choices=[('create', 'Create'), ('view', 'View'), ('update', 'Update'), ('delete', 'Delete')], max_length=16, verbose_name='Action'), - ), - ] diff --git a/apps/audits/migrations/0015_auto_20221011_1745.py b/apps/audits/migrations/0015_auto_20221011_1745.py deleted file mode 100644 index dafd35dc8..000000000 --- a/apps/audits/migrations/0015_auto_20221011_1745.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.2.14 on 2022-10-11 09:45 - -import common.db.encoder -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0014_auto_20220505_1902'), - ] - - operations = [ - migrations.AddField( - model_name='operatelog', - name='after', - field=models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True), - ), - migrations.AddField( - model_name='operatelog', - name='before', - field=models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True), - ), - ] diff --git a/apps/audits/migrations/0016_auto_20221111_1919.py b/apps/audits/migrations/0016_auto_20221111_1919.py deleted file mode 100644 index 226588e7b..000000000 --- a/apps/audits/migrations/0016_auto_20221111_1919.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 3.2.14 on 2022-11-11 11:19 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('audits', '0015_auto_20221011_1745'), - ] - - operations = [ - migrations.AlterField( - model_name='ftplog', - name='operate', - field=models.CharField( - choices=[('mkdir', 'Mkdir'), ('rmdir', 'Rmdir'), ('delete', 'Delete'), ('upload', 'Upload'), - ('rename', 'Rename'), ('symlink', 'Symlink'), ('download', 'Download')], max_length=16, - verbose_name='Operate'), - ), - migrations.AlterField( - model_name='operatelog', - name='action', - field=models.CharField(choices=[ - ('view', 'View'), ('update', 'Update'), ('delete', 'Delete'), - ('create', 'Create'), ('connect', 'Connect'), ('login', 'Login'), - ('change_password', 'Change password') - ], max_length=16, verbose_name='Action'), - ), - migrations.AlterField( - model_name='userloginlog', - name='status', - field=models.BooleanField(choices=[(1, 'Success'), (0, 'Failed')], default=1, verbose_name='Status'), - ), - ] diff --git a/apps/audits/migrations/0017_auto_20221220_1757.py b/apps/audits/migrations/0017_auto_20221220_1757.py deleted file mode 100644 index b879648e8..000000000 --- a/apps/audits/migrations/0017_auto_20221220_1757.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 09:57 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('audits', '0016_auto_20221111_1919'), - ] - - operations = [ - migrations.RenameField( - model_name='ftplog', - old_name='system_user', - new_name='account', - ), - migrations.AlterField( - model_name='ftplog', - name='account', - field=models.CharField(default='', max_length=128, verbose_name='Account'), - preserve_default=False, - ), - ] diff --git a/apps/audits/migrations/0018_operatelog_resource_id.py b/apps/audits/migrations/0018_operatelog_resource_id.py deleted file mode 100644 index 9e99e1e3f..000000000 --- a/apps/audits/migrations/0018_operatelog_resource_id.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.2.14 on 2023-01-03 08:53 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0017_auto_20221220_1757'), - ] - - operations = [ - migrations.AddField( - model_name='operatelog', - name='resource_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Resource'), - ), - migrations.AlterModelOptions( - name='operatelog', - options={'ordering': ('-datetime',), 'verbose_name': 'Operate log'}, - ), - ] diff --git a/apps/audits/migrations/0019_alter_operatelog_options.py b/apps/audits/migrations/0019_alter_operatelog_options.py deleted file mode 100644 index 2039fb221..000000000 --- a/apps/audits/migrations/0019_alter_operatelog_options.py +++ /dev/null @@ -1,13 +0,0 @@ -# Generated by Django 3.2.16 on 2023-01-10 06:45 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0018_operatelog_resource_id'), - ] - - operations = [ - ] diff --git a/apps/audits/migrations/0020_auto_20230117_1004.py b/apps/audits/migrations/0020_auto_20230117_1004.py deleted file mode 100644 index 4270b0642..000000000 --- a/apps/audits/migrations/0020_auto_20230117_1004.py +++ /dev/null @@ -1,50 +0,0 @@ -# Generated by Django 3.2.14 on 2023-01-17 02:04 - -import common.db.encoder -from django.db import migrations, models - -from audits.backends.db import OperateLogStore - - -def migrate_operate_log_after_before(apps, schema_editor): - operate_log_model = apps.get_model("audits", "OperateLog") - db_alias = schema_editor.connection.alias - count, batch_size = 0, 1000 - - while True: - operate_logs = [] - queryset = operate_log_model.objects.using(db_alias).all()[count:count + batch_size] - if not queryset: - break - count += len(queryset) - for inst in queryset: - before, after, diff = inst.before, inst.after, dict() - if not any([before, after]): - continue - diff = OperateLogStore.convert_before_after_to_diff(before, after) - inst.diff = diff - operate_logs.append(inst) - operate_log_model.objects.bulk_update(operate_logs, ['diff']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0019_alter_operatelog_options'), - ] - - operations = [ - migrations.AddField( - model_name='operatelog', - name='diff', - field=models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True), - ), - migrations.RunPython(migrate_operate_log_after_before), - migrations.RemoveField(model_name='operatelog', name='after', ), - migrations.RemoveField(model_name='operatelog', name='before', ), - migrations.AlterField( - model_name='operatelog', - name='resource_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=128, verbose_name='Resource'), - ), - ] diff --git a/apps/audits/migrations/0021_auto_20230207_0857.py b/apps/audits/migrations/0021_auto_20230207_0857.py deleted file mode 100644 index 4e66c63f0..000000000 --- a/apps/audits/migrations/0021_auto_20230207_0857.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-07 00:57 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0020_auto_20230117_1004'), - ('ops', '0023_auto_20220912_0021'), - ] - - operations = [ - migrations.CreateModel( - name='ActivityLog', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('type', models.CharField(choices=[('O', 'Operate log'), ('S', 'Session log'), ('L', 'Login log'), ('T', 'Task')], default=None, max_length=2, null=True, verbose_name='Activity type')), - ('resource_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Resource')), - ('datetime', models.DateTimeField(auto_now=True, db_index=True, verbose_name='Datetime')), - ('detail', models.TextField(blank=True, default='', verbose_name='Detail')), - ('detail_id', models.CharField(default=None, max_length=36, null=True, verbose_name='Detail ID')), - ], - options={ - 'verbose_name': 'Activity log', - 'ordering': ('-datetime',), - }, - ), - migrations.CreateModel( - name='JobLog', - fields=[ - ], - options={ - 'verbose_name': 'Job audit log', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('ops.jobexecution',), - ), - ] diff --git a/apps/audits/migrations/0022_auto_20230605_1555.py b/apps/audits/migrations/0022_auto_20230605_1555.py deleted file mode 100644 index c5ec8847f..000000000 --- a/apps/audits/migrations/0022_auto_20230605_1555.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.2.17 on 2023-06-05 07:55 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0021_auto_20230207_0857'), - ] - - operations = [ - migrations.AddField( - model_name='ftplog', - name='has_file', - field=models.BooleanField(default=False, verbose_name='File'), - ), - migrations.AddField( - model_name='ftplog', - name='session', - field=models.CharField(default=uuid.uuid4, max_length=36, verbose_name='Session'), - ), - migrations.AlterField( - model_name='ftplog', - name='operate', - field=models.CharField(choices=[('mkdir', 'Mkdir'), ('rmdir', 'Rmdir'), ('delete', 'Delete'), ('upload', 'Upload'), ('rename', 'Rename'), ('symlink', 'Symlink'), ('download', 'Download'), ('rename_dir', 'Rename dir')], max_length=16, verbose_name='Operate'), - ), - ] diff --git a/apps/audits/migrations/0023_auto_20230906_1322.py b/apps/audits/migrations/0023_auto_20230906_1322.py deleted file mode 100644 index 34928eef6..000000000 --- a/apps/audits/migrations/0023_auto_20230906_1322.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-06 05:31 - -import django.utils.timezone -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0022_auto_20230605_1555'), - ] - - operations = [ - migrations.AlterField( - model_name='ftplog', - name='date_start', - field=models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Date start'), - ), - migrations.AlterField( - model_name='operatelog', - name='action', - field=models.CharField(choices=[('view', 'View'), ('update', 'Update'), ('delete', 'Delete'), ('create', 'Create'), ('download', 'Download'), ('connect', 'Connect'), ('login', 'Login'), ('change_password', 'Change password'), ('accept', 'Accept'), ('review', 'Review'), ('notice', 'Notifications'), ('reject', 'Reject'), ('approve', 'Approve'), ('close', 'Close')], max_length=16, verbose_name='Action'), - ), - migrations.AlterField( - model_name='userloginlog', - name='datetime', - field=models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Login Date'), - ), - ] diff --git a/apps/audits/migrations/0024_usersession.py b/apps/audits/migrations/0024_usersession.py deleted file mode 100644 index 880099086..000000000 --- a/apps/audits/migrations/0024_usersession.py +++ /dev/null @@ -1,40 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-15 08:58 - -import uuid - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('audits', '0023_auto_20230906_1322'), - ] - - operations = [ - migrations.CreateModel( - name='UserSession', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('ip', models.GenericIPAddressField(verbose_name='Login IP')), - ('key', models.CharField(max_length=128, verbose_name='Session key')), - ('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')), - ('type', models.CharField(choices=[('W', 'Web'), ('T', 'Terminal'), ('U', 'Unknown')], max_length=2, - verbose_name='Login type')), - ('backend', models.CharField(default='', max_length=32, verbose_name='Auth backend')), - ('date_created', models.DateTimeField(blank=True, null=True, verbose_name='Date created')), - ('date_expired', - models.DateTimeField(blank=True, db_index=True, null=True, verbose_name='Date expired')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sessions', - to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'verbose_name': 'User session', - 'ordering': ['-date_created'], - 'permissions': [('offline_usersession', 'Offline user session')], - }, - ), - ] diff --git a/apps/audits/migrations/0025_remove_usersession_date_expired.py b/apps/audits/migrations/0025_remove_usersession_date_expired.py deleted file mode 100644 index 0b495f72d..000000000 --- a/apps/audits/migrations/0025_remove_usersession_date_expired.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-18 08:01 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0024_usersession'), - ] - - operations = [ - migrations.RemoveField( - model_name='usersession', - name='date_expired', - ), - ] diff --git a/apps/authentication/migrations/0001_initial.py b/apps/authentication/migrations/0001_initial.py index 4c2251138..7b332051f 100644 --- a/apps/authentication/migrations/0001_initial.py +++ b/apps/authentication/migrations/0001_initial.py @@ -1,9 +1,9 @@ -# Generated by Django 2.1.7 on 2019-02-28 08:07 +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import common.db.models -from django.conf import settings +import authentication.models.access_key +import authentication.models.connection_token +import common.db.fields from django.db import migrations, models -import django.db.models.deletion import uuid @@ -12,46 +12,116 @@ class Migration(migrations.Migration): initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('users', '0019_auto_20190304_1459'), ] - state_operations = [ + operations = [ migrations.CreateModel( name='AccessKey', fields=[ - ('id', - models.UUIDField(default=uuid.uuid4, editable=False, - primary_key=True, serialize=False, - verbose_name='AccessKeyID')), - ('secret', - models.UUIDField(default=uuid.uuid4, editable=False, - verbose_name='AccessKeySecret')), - ('user', models.ForeignKey( - on_delete=common.db.models.CASCADE_SIGNAL_SKIP, - related_name='access_keys', - to=settings.AUTH_USER_MODEL, verbose_name='User')), + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, verbose_name='AccessKeyID')), + ('secret', models.CharField(default=authentication.models.access_key.default_secret, max_length=36, verbose_name='AccessKeySecret')), + ('ip_group', models.JSONField(default=authentication.models.access_key.default_ip_group, verbose_name='IP group')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('date_last_used', models.DateTimeField(blank=True, null=True, verbose_name='Date last used')), + ('date_created', models.DateTimeField(auto_now_add=True)), ], + options={ + 'verbose_name': 'Access key', + }, + ), + migrations.CreateModel( + name='ConnectionToken', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('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')), + ('value', models.CharField(default='', max_length=64, verbose_name='Value')), + ('account', models.CharField(max_length=128, verbose_name='Account name')), + ('input_username', models.CharField(blank=True, default='', max_length=128, verbose_name='Input username')), + ('input_secret', common.db.fields.EncryptTextField(blank=True, default='', max_length=64, verbose_name='Input secret')), + ('protocol', models.CharField(default='ssh', max_length=16, verbose_name='Protocol')), + ('connect_method', models.CharField(max_length=32, verbose_name='Connect method')), + ('connect_options', models.JSONField(default=dict, verbose_name='Connect options')), + ('user_display', models.CharField(default='', max_length=128, verbose_name='User display')), + ('asset_display', models.CharField(default='', max_length=128, verbose_name='Asset display')), + ('is_reusable', models.BooleanField(default=False, verbose_name='Reusable')), + ('date_expired', models.DateTimeField(default=authentication.models.connection_token.date_expired_default, verbose_name='Date expired')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ], + options={ + 'verbose_name': 'Connection token', + 'ordering': ('-date_expired',), + 'permissions': [('expire_connectiontoken', 'Can expire connection token'), ('reuse_connectiontoken', 'Can reuse connection token')], + }, + ), + migrations.CreateModel( + name='Passkey', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=255, verbose_name='Name')), + ('is_active', models.BooleanField(default=True, verbose_name='Enabled')), + ('platform', models.CharField(default='', max_length=255, verbose_name='Platform')), + ('added_on', models.DateTimeField(auto_now_add=True, verbose_name='Added on')), + ('date_last_used', models.DateTimeField(default=None, null=True, verbose_name='Date last used')), + ('credential_id', models.CharField(max_length=255, unique=True, verbose_name='Credential ID')), + ('token', models.CharField(max_length=255, verbose_name='Token')), + ], + options={ + 'abstract': False, + }, ), migrations.CreateModel( name='PrivateToken', fields=[ - ('key', - models.CharField(max_length=40, primary_key=True, - serialize=False, verbose_name='Key')), - ('created', models.DateTimeField(auto_now_add=True, - verbose_name='Created')), - ('user', models.OneToOneField( - on_delete=django.db.models.deletion.CASCADE, - related_name='auth_token', - to=settings.AUTH_USER_MODEL, verbose_name='User')), + ('key', models.CharField(max_length=40, primary_key=True, serialize=False, verbose_name='Key')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), + ('date_last_used', models.DateTimeField(blank=True, null=True, verbose_name='Date last used')), ], options={ 'verbose_name': 'Private Token', }, ), - ] - - operations = [ - migrations.SeparateDatabaseAndState(state_operations=state_operations) + migrations.CreateModel( + name='SSOToken', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('authkey', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, verbose_name='Token')), + ('expired', models.BooleanField(default=False, verbose_name='Expired')), + ], + options={ + 'verbose_name': 'SSO token', + }, + ), + migrations.CreateModel( + name='TempToken', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('username', models.CharField(max_length=128, verbose_name='Username')), + ('secret', models.CharField(max_length=64, verbose_name='Secret')), + ('verified', models.BooleanField(default=False, verbose_name='Verified')), + ('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')), + ('date_expired', models.DateTimeField(verbose_name='Date expired')), + ], + options={ + 'verbose_name': 'Temporary token', + }, + ), ] diff --git a/apps/authentication/migrations/0002_auto_20190729_1423.py b/apps/authentication/migrations/0002_auto_20190729_1423.py index 6e971e96b..7a35c0105 100644 --- a/apps/authentication/migrations/0002_auto_20190729_1423.py +++ b/apps/authentication/migrations/0002_auto_20190729_1423.py @@ -1,23 +1,69 @@ -# Generated by Django 2.1.7 on 2019-07-29 06:23 +# Generated by Django 4.1.13 on 2024-05-09 03:16 +import common.db.models +from django.conf import settings from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): + + initial = True + dependencies = [ + ('assets', '0002_auto_20180105_1807'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('tickets', '0001_initial'), ('authentication', '0001_initial'), ] operations = [ migrations.AddField( - model_name='accesskey', - name='date_created', - field=models.DateTimeField(auto_now_add=True), - preserve_default=False, + model_name='ssotoken', + name='user', + field=models.ForeignKey(db_constraint=False, on_delete=common.db.models.CASCADE_SIGNAL_SKIP, to=settings.AUTH_USER_MODEL, verbose_name='User'), + ), + migrations.AddField( + model_name='privatetoken', + name='user', + field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='auth_token', to=settings.AUTH_USER_MODEL, verbose_name='User'), + ), + migrations.AddField( + model_name='passkey', + name='user', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='connectiontoken', + name='asset', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='connection_tokens', to='assets.asset', verbose_name='Asset'), + ), + migrations.AddField( + model_name='connectiontoken', + name='from_ticket', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='connection_token', to='tickets.applyloginassetticket', verbose_name='From ticket'), + ), + migrations.AddField( + model_name='connectiontoken', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='connection_tokens', to=settings.AUTH_USER_MODEL, verbose_name='User'), ), migrations.AddField( model_name='accesskey', - name='is_active', - field=models.BooleanField(default=True, verbose_name='Active'), + name='user', + field=models.ForeignKey(on_delete=common.db.models.CASCADE_SIGNAL_SKIP, related_name='access_keys', to=settings.AUTH_USER_MODEL, verbose_name='User'), + ), + migrations.CreateModel( + name='SuperConnectionToken', + fields=[ + ], + options={ + 'verbose_name': 'Super connection token', + 'permissions': [('view_superconnectiontokensecret', 'Can view super connection token secret')], + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('authentication.connectiontoken',), ), ] diff --git a/apps/authentication/migrations/0003_loginconfirmsetting.py b/apps/authentication/migrations/0003_loginconfirmsetting.py deleted file mode 100644 index c8043bc87..000000000 --- a/apps/authentication/migrations/0003_loginconfirmsetting.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 2.2.5 on 2019-10-31 10:23 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('authentication', '0002_auto_20190729_1423'), - ] - - operations = [ - migrations.CreateModel( - name='LoginConfirmSetting', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('reviewers', models.ManyToManyField(blank=True, related_name='review_login_confirm_settings', to=settings.AUTH_USER_MODEL, verbose_name='Reviewers')), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='login_confirm_setting', to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'abstract': False, - }, - ), - ] diff --git a/apps/authentication/migrations/0004_ssotoken.py b/apps/authentication/migrations/0004_ssotoken.py deleted file mode 100644 index 57d2f9805..000000000 --- a/apps/authentication/migrations/0004_ssotoken.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-31 08:36 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('authentication', '0003_loginconfirmsetting'), - ] - - operations = [ - migrations.CreateModel( - name='SSOToken', - fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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')), - ('authkey', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False, verbose_name='Token')), - ('expired', models.BooleanField(default=False, verbose_name='Expired')), - ('user', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'abstract': False, - }, - ), - ] diff --git a/apps/authentication/migrations/0005_delete_loginconfirmsetting.py b/apps/authentication/migrations/0005_delete_loginconfirmsetting.py deleted file mode 100644 index cbf01a735..000000000 --- a/apps/authentication/migrations/0005_delete_loginconfirmsetting.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 3.1.12 on 2021-09-26 11:13 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0004_ssotoken'), - ] - - operations = [ - migrations.DeleteModel( - name='LoginConfirmSetting', - ), - ] diff --git a/apps/authentication/migrations/0006_auto_20211227_1059.py b/apps/authentication/migrations/0006_auto_20211227_1059.py deleted file mode 100644 index b01758bbd..000000000 --- a/apps/authentication/migrations/0006_auto_20211227_1059.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-27 02:59 - -import common.db.models -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('authentication', '0005_delete_loginconfirmsetting'), - ] - - operations = [ - migrations.AlterField( - model_name='ssotoken', - name='user', - field=models.ForeignKey(db_constraint=False, on_delete=common.db.models.CASCADE_SIGNAL_SKIP, to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - ] diff --git a/apps/authentication/migrations/0007_connectiontoken.py b/apps/authentication/migrations/0007_connectiontoken.py deleted file mode 100644 index 6c0b437da..000000000 --- a/apps/authentication/migrations/0007_connectiontoken.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 3.1.12 on 2022-02-11 06:01 -import uuid - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0006_auto_20211227_1059'), - ] - - operations = [ - migrations.CreateModel( - name='ConnectionToken', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False),), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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')), - ], - options={'verbose_name': 'Connection token'}, - ), - migrations.AlterModelOptions( - name='accesskey', - options={'verbose_name': 'Access key'}, - ), - migrations.AlterModelOptions( - name='ssotoken', - options={'verbose_name': 'SSO token'}, - ), - ] diff --git a/apps/authentication/migrations/0008_superconnectiontoken.py b/apps/authentication/migrations/0008_superconnectiontoken.py deleted file mode 100644 index 82e956a24..000000000 --- a/apps/authentication/migrations/0008_superconnectiontoken.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-02 11:53 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0007_connectiontoken'), - ] - - operations = [ - migrations.CreateModel( - name='SuperConnectionToken', - fields=[ - ], - options={ - 'verbose_name': 'Super connection token', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('authentication.connectiontoken',), - ), - ] diff --git a/apps/authentication/migrations/0009_auto_20220310_0616.py b/apps/authentication/migrations/0009_auto_20220310_0616.py deleted file mode 100644 index 652aa2ea4..000000000 --- a/apps/authentication/migrations/0009_auto_20220310_0616.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-09 22:16 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0008_superconnectiontoken'), - ] - - operations = [ - migrations.AlterModelOptions( - name='connectiontoken', - options={'permissions': [('view_connectiontokensecret', 'Can view connection token secret')], 'verbose_name': 'Connection token'}, - ), - ] diff --git a/apps/authentication/migrations/0010_temptoken.py b/apps/authentication/migrations/0010_temptoken.py deleted file mode 100644 index b76ae0f97..000000000 --- a/apps/authentication/migrations/0010_temptoken.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-08 07:04 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0009_auto_20220310_0616'), - ] - - operations = [ - migrations.CreateModel( - name='TempToken', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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')), - ('username', models.CharField(max_length=128, verbose_name='Username')), - ('secret', models.CharField(max_length=64, verbose_name='Secret')), - ('verified', models.BooleanField(default=False, verbose_name='Verified')), - ('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')), - ('date_expired', models.DateTimeField(verbose_name='Date expired')), - ], - options={ - 'verbose_name': 'Temporary token', - }, - ), - ] diff --git a/apps/authentication/migrations/0011_auto_20220705_1940.py b/apps/authentication/migrations/0011_auto_20220705_1940.py deleted file mode 100644 index f965c9486..000000000 --- a/apps/authentication/migrations/0011_auto_20220705_1940.py +++ /dev/null @@ -1,92 +0,0 @@ -# Generated by Django 3.2.12 on 2022-07-05 11:40 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - -import authentication.models - - -class Migration(migrations.Migration): - dependencies = [ - ('applications', '0021_auto_20220629_1826'), - ('assets', '0091_auto_20220629_1826'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('authentication', '0010_temptoken'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='application', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='connection_tokens', to='applications.application', - verbose_name='Application'), - ), - migrations.AddField( - model_name='connectiontoken', - name='application_display', - field=models.CharField(default='', max_length=128, verbose_name='Application display'), - ), - migrations.AddField( - model_name='connectiontoken', - name='asset', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='connection_tokens', to='assets.asset', verbose_name='Asset'), - ), - migrations.AddField( - model_name='connectiontoken', - name='asset_display', - field=models.CharField(default='', max_length=128, verbose_name='Asset display'), - ), - migrations.AddField( - model_name='connectiontoken', - name='date_expired', - field=models.DateTimeField(default=authentication.models.date_expired_default, verbose_name='Date expired'), - ), - migrations.AddField( - model_name='connectiontoken', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AddField( - model_name='connectiontoken', - name='secret', - field=models.CharField(default='', max_length=64, verbose_name='Secret'), - ), - migrations.AddField( - model_name='connectiontoken', - name='system_user', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='connection_tokens', to='assets.systemuser', - verbose_name='System user'), - ), - migrations.AddField( - model_name='connectiontoken', - name='system_user_display', - field=models.CharField(default='', max_length=128, verbose_name='System user display'), - ), - migrations.AddField( - model_name='connectiontoken', - name='type', - field=models.CharField(choices=[('asset', 'Asset'), ('application', 'Application')], default='asset', - max_length=16, verbose_name='Type'), - ), - migrations.AddField( - model_name='connectiontoken', - name='user', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, - related_name='connection_tokens', to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - migrations.AddField( - model_name='connectiontoken', - name='user_display', - field=models.CharField(default='', max_length=128, verbose_name='User display'), - ), - migrations.AlterModelOptions( - name='connectiontoken', - options={'ordering': ('-date_expired',), - 'permissions': [('view_connectiontokensecret', 'Can view connection token secret')], - 'verbose_name': 'Connection token'}, - ), - ] diff --git a/apps/authentication/migrations/0012_auto_20220816_1629.py b/apps/authentication/migrations/0012_auto_20220816_1629.py deleted file mode 100644 index 1557057c5..000000000 --- a/apps/authentication/migrations/0012_auto_20220816_1629.py +++ /dev/null @@ -1,59 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-16 08:29 - -from django.db import migrations, models - - -def migrate_system_user_to_account(apps, schema_editor): - connection_token_model = apps.get_model("authentication", "ConnectionToken") - count = 0 - bulk_size = 10000 - - while True: - connection_tokens = connection_token_model.objects \ - .prefetch_related('system_user')[count:bulk_size] - if not connection_tokens: - break - count += len(connection_tokens) - updated = [] - for connection_token in connection_tokens: - if not connection_token.system_user: - continue - connection_token.account_username = connection_token.system_user.username - updated.append(connection_token) - connection_token_model.objects.bulk_update(updated, ['account_username']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0011_auto_20220705_1940'), - ] - - operations = [ - migrations.RemoveField( - model_name='connectiontoken', - name='application', - ), - migrations.RemoveField( - model_name='connectiontoken', - name='application_display', - ), - migrations.RemoveField( - model_name='connectiontoken', - name='system_user_display', - ), - migrations.AddField( - model_name='connectiontoken', - name='account_username', - field=models.CharField(default='', max_length=128, verbose_name='Account'), - ), - migrations.RunPython(migrate_system_user_to_account), - migrations.RemoveField( - model_name='connectiontoken', - name='system_user', - ), - migrations.RemoveField( - model_name='connectiontoken', - name='type', - ), - ] diff --git a/apps/authentication/migrations/0013_connectiontoken_protocol.py b/apps/authentication/migrations/0013_connectiontoken_protocol.py deleted file mode 100644 index 3ba4785b0..000000000 --- a/apps/authentication/migrations/0013_connectiontoken_protocol.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.14 on 2022-10-27 12:01 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0012_auto_20220816_1629'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='protocol', - field=models.CharField(default='ssh', max_length=16, verbose_name='Protocol'), - ), - ] diff --git a/apps/authentication/migrations/0014_auto_20221122_2152.py b/apps/authentication/migrations/0014_auto_20221122_2152.py deleted file mode 100644 index 483b6d5f0..000000000 --- a/apps/authentication/migrations/0014_auto_20221122_2152.py +++ /dev/null @@ -1,51 +0,0 @@ -# Generated by Django 3.2.14 on 2022-11-22 13:52 - -from django.db import migrations, models - -import common.db.fields - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0013_connectiontoken_protocol'), - ] - - operations = [ - migrations.RenameField( - model_name='connectiontoken', - old_name='account_username', - new_name='account_name' - ), - migrations.AlterField( - model_name='connectiontoken', - name='account_name', - field=models.CharField(max_length=128, verbose_name='Account name'), - ), - migrations.AddField( - model_name='connectiontoken', - name='input_username', - field=models.CharField(blank=True, default='', max_length=128, verbose_name='Input username'), - ), - migrations.AddField( - model_name='connectiontoken', - name='input_secret', - field=common.db.fields.EncryptCharField(blank=True, default='', max_length=128, - verbose_name='Input secret'), - ), - migrations.RenameField( - model_name='connectiontoken', - old_name='secret', - new_name='value', - ), - migrations.AlterField( - model_name='connectiontoken', - name='value', - field=models.CharField(default='', max_length=64, verbose_name='Value'), - ), - migrations.AddField( - model_name='connectiontoken', - name='connect_method', - field=models.CharField(default='web_ui', max_length=32, verbose_name='Connect method'), - preserve_default=False, - ), - ] diff --git a/apps/authentication/migrations/0015_auto_20221205_1136.py b/apps/authentication/migrations/0015_auto_20221205_1136.py deleted file mode 100644 index 7de71fe5c..000000000 --- a/apps/authentication/migrations/0015_auto_20221205_1136.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-05 03:36 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0014_auto_20221122_2152'), - ] - - operations = [ - migrations.RenameField( - model_name='connectiontoken', - old_name='account_name', - new_name='account', - ), - ] diff --git a/apps/authentication/migrations/0016_auto_20221220_1956.py b/apps/authentication/migrations/0016_auto_20221220_1956.py deleted file mode 100644 index d1480629c..000000000 --- a/apps/authentication/migrations/0016_auto_20221220_1956.py +++ /dev/null @@ -1,58 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0015_auto_20221205_1136'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='ssotoken', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='temptoken', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='connectiontoken', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='connectiontoken', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='ssotoken', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='ssotoken', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='temptoken', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='temptoken', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - ] diff --git a/apps/authentication/migrations/0017_auto_20230105_1743.py b/apps/authentication/migrations/0017_auto_20230105_1743.py deleted file mode 100644 index f4f9bff69..000000000 --- a/apps/authentication/migrations/0017_auto_20230105_1743.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.2.14 on 2023-01-05 09:43 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0028_remove_app_tickets'), - ('authentication', '0016_auto_20221220_1956'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='from_ticket', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='connection_token', to='tickets.applyloginassetticket', verbose_name='From ticket'), - ), - migrations.AddField( - model_name='connectiontoken', - name='is_active', - field=models.BooleanField(default=True, verbose_name='Active'), - ), - ] diff --git a/apps/authentication/migrations/0018_alter_connectiontoken_input_secret.py b/apps/authentication/migrations/0018_alter_connectiontoken_input_secret.py deleted file mode 100644 index b11598066..000000000 --- a/apps/authentication/migrations/0018_alter_connectiontoken_input_secret.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-14 08:49 - -import common.db.fields -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0017_auto_20230105_1743'), - ] - - operations = [ - migrations.AlterField( - model_name='connectiontoken', - name='input_secret', - field=common.db.fields.EncryptTextField(blank=True, default='', max_length=64, verbose_name='Input secret'), - ), - ] diff --git a/apps/authentication/migrations/0019_connectiontoken_is_reusable.py b/apps/authentication/migrations/0019_connectiontoken_is_reusable.py deleted file mode 100644 index 92ccc892a..000000000 --- a/apps/authentication/migrations/0019_connectiontoken_is_reusable.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.17 on 2023-05-08 07:34 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0018_alter_connectiontoken_input_secret'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='is_reusable', - field=models.BooleanField(default=False, verbose_name='Reusable'), - ), - ] diff --git a/apps/authentication/migrations/0020_connectiontoken_connect_options.py b/apps/authentication/migrations/0020_connectiontoken_connect_options.py deleted file mode 100644 index 15447c9b6..000000000 --- a/apps/authentication/migrations/0020_connectiontoken_connect_options.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.17 on 2023-06-05 07:28 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0019_connectiontoken_is_reusable'), - ] - - operations = [ - migrations.AddField( - model_name='connectiontoken', - name='connect_options', - field=models.JSONField(default=dict, verbose_name='Connect options'), - ), - ] diff --git a/apps/authentication/migrations/0021_auto_20230713_1459.py b/apps/authentication/migrations/0021_auto_20230713_1459.py deleted file mode 100644 index 03913f766..000000000 --- a/apps/authentication/migrations/0021_auto_20230713_1459.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.2.19 on 2023-07-13 06:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0020_connectiontoken_connect_options'), - ] - - operations = [ - migrations.AlterModelOptions( - name='connectiontoken', - options={'ordering': ('-date_expired',), - 'permissions': [('expire_connectiontoken', 'Can expire connection token'), - ('reuse_connectiontoken', 'Can reuse connection token')], - 'verbose_name': 'Connection token'}, - ), - migrations.AlterModelOptions( - name='superconnectiontoken', - options={'permissions': [('view_superconnectiontokensecret', 'Can view super connection token secret')], - 'verbose_name': 'Super connection token'}, - ), - ] diff --git a/apps/authentication/migrations/0022_passkey.py b/apps/authentication/migrations/0022_passkey.py deleted file mode 100644 index 322d5cf6f..000000000 --- a/apps/authentication/migrations/0022_passkey.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-08 08:10 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('authentication', '0021_auto_20230713_1459'), - ] - - operations = [ - migrations.CreateModel( - name='Passkey', - 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')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=255, verbose_name='Name')), - ('is_active', models.BooleanField(default=True, verbose_name='Enabled')), - ('platform', models.CharField(default='', max_length=255, verbose_name='Platform')), - ('added_on', models.DateTimeField(auto_now_add=True, verbose_name='Added on')), - ('date_last_used', models.DateTimeField(default=None, null=True, verbose_name='Date last used')), - ('credential_id', models.CharField(max_length=255, unique=True, verbose_name='Credential ID')), - ('token', models.CharField(max_length=255, verbose_name='Token')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'abstract': False, - }, - ), - ] diff --git a/apps/authentication/migrations/0023_auto_20231010_1101.py b/apps/authentication/migrations/0023_auto_20231010_1101.py deleted file mode 100644 index 81920dfd7..000000000 --- a/apps/authentication/migrations/0023_auto_20231010_1101.py +++ /dev/null @@ -1,57 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-10 02:47 - -import uuid -import authentication.models.access_key -from django.db import migrations, models - - -def migrate_access_key_secret(apps, schema_editor): - access_key_model = apps.get_model('authentication', 'AccessKey') - db_alias = schema_editor.connection.alias - - batch_size = 100 - count = 0 - - while True: - access_keys = access_key_model.objects.using(db_alias).all()[count:count + batch_size] - if not access_keys: - break - - count += len(access_keys) - access_keys_updated = [] - for access_key in access_keys: - s = access_key.secret - if len(s) != 32 or not s.islower(): - continue - try: - access_key.secret = '%s-%s-%s-%s-%s' % (s[:8], s[8:12], s[12:16], s[16:20], s[20:]) - access_keys_updated.append(access_key) - except (ValueError, IndexError): - pass - access_key_model.objects.bulk_update(access_keys_updated, fields=['secret']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('authentication', '0022_passkey'), - ] - - operations = [ - migrations.AddField( - model_name='accesskey', - name='date_last_used', - field=models.DateTimeField(blank=True, null=True, verbose_name='Date last used'), - ), - migrations.AddField( - model_name='privatetoken', - name='date_last_used', - field=models.DateTimeField(blank=True, null=True, verbose_name='Date last used'), - ), - migrations.AlterField( - model_name='accesskey', - name='secret', - field=models.CharField(default=authentication.models.access_key.default_secret, max_length=36, verbose_name='AccessKeySecret'), - ), - migrations.RunPython(migrate_access_key_secret), - ] diff --git a/apps/authentication/migrations/0024_accesskey_ip_group.py b/apps/authentication/migrations/0024_accesskey_ip_group.py deleted file mode 100644 index e34d81751..000000000 --- a/apps/authentication/migrations/0024_accesskey_ip_group.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-31 05:37 - -import authentication.models.access_key -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('authentication', '0023_auto_20231010_1101'), - ] - - operations = [ - migrations.AddField( - model_name='accesskey', - name='ip_group', - field=models.JSONField(default=authentication.models.access_key.default_ip_group, verbose_name='IP group'), - ), - ] diff --git a/apps/common/migrations/0001_initial.py b/apps/common/migrations/0001_initial.py deleted file mode 100644 index 2b612dc1d..000000000 --- a/apps/common/migrations/0001_initial.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-11 05:35 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.manager - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ] - - operations = [ - migrations.CreateModel( - name='Settings', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('value', models.TextField(verbose_name='Value')), - ('enabled', models.BooleanField(default=True, verbose_name='Enabled')), - ('comment', models.TextField(verbose_name='Comment')), - ], - managers=[ - ('configs', django.db.models.manager.Manager()), - ], - ), - ] diff --git a/apps/common/migrations/0002_auto_20180111_1407.py b/apps/common/migrations/0002_auto_20180111_1407.py deleted file mode 100644 index 7c74b9d2b..000000000 --- a/apps/common/migrations/0002_auto_20180111_1407.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-11 06:07 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('common', '0001_initial'), - ] - - operations = [ - migrations.RenameModel( - old_name='Settings', - new_name='Setting', - ), - migrations.AlterModelManagers( - name='setting', - managers=[ - ], - ), - migrations.AlterModelTable( - name='setting', - table='settings', - ), - ] diff --git a/apps/common/migrations/0003_setting_category.py b/apps/common/migrations/0003_setting_category.py deleted file mode 100644 index 234518287..000000000 --- a/apps/common/migrations/0003_setting_category.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-22 03:54 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('common', '0002_auto_20180111_1407'), - ] - - operations = [ - migrations.AddField( - model_name='setting', - name='category', - field=models.CharField(default='default', max_length=128), - ), - ] diff --git a/apps/common/migrations/0004_setting_encrypted.py b/apps/common/migrations/0004_setting_encrypted.py deleted file mode 100644 index d6862643f..000000000 --- a/apps/common/migrations/0004_setting_encrypted.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1 on 2018-09-03 03:32 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('common', '0003_setting_category'), - ] - - operations = [ - migrations.AddField( - model_name='setting', - name='encrypted', - field=models.BooleanField(default=False), - ), - ] diff --git a/apps/common/migrations/0005_auto_20190221_1902.py b/apps/common/migrations/0005_auto_20190221_1902.py deleted file mode 100644 index 997ca7a13..000000000 --- a/apps/common/migrations/0005_auto_20190221_1902.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-21 11:02 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('common', '0004_setting_encrypted'), - ] - - operations = [ - migrations.AlterModelOptions( - name='setting', - options={'verbose_name': 'Setting'}, - ), - ] diff --git a/apps/common/migrations/0006_auto_20190304_1515.py b/apps/common/migrations/0006_auto_20190304_1515.py deleted file mode 100644 index 77303a39a..000000000 --- a/apps/common/migrations/0006_auto_20190304_1515.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.1.7 on 2019-03-04 07:15 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('common', '0005_auto_20190221_1902'), - ] - - database_operations = [ - migrations.AlterModelTable('setting', 'settings_setting') - ] - state_operations = [migrations.DeleteModel('setting')] - - operations = [ - migrations.SeparateDatabaseAndState( - database_operations=database_operations, - state_operations=state_operations - ) - ] diff --git a/apps/i18n/lina/en.json b/apps/i18n/lina/en.json index 2d232cd95..a3a1d06f1 100644 --- a/apps/i18n/lina/en.json +++ b/apps/i18n/lina/en.json @@ -845,7 +845,7 @@ "Radius": "Radius", "Ranking": "Ranking", "RazorNotSupport": "RDP Client Session, Monitoring Not Supported", - "ReLogin": "Log in Again", + "ReLogin": "Log in again", "ReLoginTitle": "Current Third-party Login User (CAS/SAML), Not Bound to MFA and Does Not Support Password Verification, Please Log in Again.", "RealTimeData": "Real-Time", "Reason": "Reason", diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index 46c688d05..64ae85121 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -131,7 +131,6 @@ INSTALLED_APPS = [ 'terminal.apps.TerminalConfig', 'audits.apps.AuditsConfig', 'authentication.apps.AuthenticationConfig', # authentication - 'applications.apps.ApplicationsConfig', 'tickets.apps.TicketsConfig', 'acls.apps.AclsConfig', 'notifications.apps.NotificationsConfig', diff --git a/apps/labels/migrations/0001_initial.py b/apps/labels/migrations/0001_initial.py index cefe74e5c..294cd5477 100644 --- a/apps/labels/migrations/0001_initial.py +++ b/apps/labels/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.1.10 on 2023-11-06 10:38 +# Generated by Django 4.1.13 on 2024-05-09 03:16 from django.db import migrations, models import django.db.models.deletion @@ -22,11 +22,11 @@ class Migration(migrations.Migration): ('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')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('internal', models.BooleanField(default=False, verbose_name='Internal')), ('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')), ('name', models.CharField(db_index=True, max_length=64, verbose_name='Name')), ('value', models.CharField(max_length=64, verbose_name='Value')), + ('internal', models.BooleanField(default=False, verbose_name='Internal')), ], options={ 'verbose_name': 'Label', @@ -44,11 +44,12 @@ class Migration(migrations.Migration): ('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')), ('res_id', models.CharField(db_index=True, max_length=36, verbose_name='Resource ID')), - ('label', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='labels.label')), + ('label', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='labeled_resources', to='labels.label', verbose_name='Label')), ('res_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.contenttype')), ], options={ - 'abstract': False, + 'verbose_name': 'Labeled resource', + 'unique_together': {('label', 'res_type', 'res_id', 'org_id')}, }, ), ] diff --git a/apps/labels/migrations/0002_auto_20231103_1659.py b/apps/labels/migrations/0002_auto_20231103_1659.py deleted file mode 100644 index 017ccf7ac..000000000 --- a/apps/labels/migrations/0002_auto_20231103_1659.py +++ /dev/null @@ -1,52 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-03 08:59 - -from django.db import migrations - - -def migrate_assets_labels(apps, schema_editor): - old_label_model = apps.get_model('assets', 'Label') - new_label_model = apps.get_model('labels', 'Label') - asset_model = apps.get_model('assets', 'Asset') - labeled_item_model = apps.get_model('labels', 'LabeledResource') - - old_labels = old_label_model.objects.all() - new_labels = [] - old_new_label_map = {} - for label in old_labels: - new_label = new_label_model(name=label.name, value=label.value, org_id=label.org_id, id=label.id) - old_new_label_map[label.id] = new_label - new_labels.append(new_label) - new_label_model.objects.bulk_create(new_labels, ignore_conflicts=True) - - label_relations = asset_model.labels.through.objects.all() - bulk_size = 1000 - count = 0 - content_type = apps.get_model('contenttypes', 'contenttype').objects.get_for_model(asset_model) - - while True: - relations = label_relations[count:count + bulk_size] - if not relations: - break - count += bulk_size - - tagged_items = [] - for relation in relations: - new_label = old_new_label_map[relation.label_id] - tagged_item = labeled_item_model( - label_id=new_label.id, res_type=content_type, - res_id=relation.asset_id, org_id=new_label.org_id - ) - tagged_items.append(tagged_item) - labeled_item_model.objects.bulk_create(tagged_items, ignore_conflicts=True) - - -class Migration(migrations.Migration): - - dependencies = [ - ('labels', '0001_initial'), - ('assets', '0125_auto_20231011_1053') - ] - - operations = [ - migrations.RunPython(migrate_assets_labels), - ] diff --git a/apps/labels/migrations/0003_alter_labeledresource_options_and_more.py b/apps/labels/migrations/0003_alter_labeledresource_options_and_more.py deleted file mode 100644 index c879b7888..000000000 --- a/apps/labels/migrations/0003_alter_labeledresource_options_and_more.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-15 10:58 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('contenttypes', '0002_remove_content_type_name'), - ('labels', '0002_auto_20231103_1659'), - ] - - operations = [ - migrations.AlterModelOptions( - name='labeledresource', - options={'verbose_name': 'Labeled resource'}, - ), - migrations.AlterField( - model_name='labeledresource', - name='label', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='labeled_resources', to='labels.label', verbose_name='Label'), - ), - migrations.AlterUniqueTogether( - name='labeledresource', - unique_together={('label', 'res_type', 'res_id', 'org_id')}, - ), - ] diff --git a/apps/locale/en/LC_MESSAGES/django.mo b/apps/locale/en/LC_MESSAGES/django.mo new file mode 100644 index 000000000..74cd9420f --- /dev/null +++ b/apps/locale/en/LC_MESSAGES/django.mo @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:375a5bd7b21f2ddd004a228ef1debcf81e32812a4392128e0acf184f3317428d +size 380 diff --git a/apps/locale/en/LC_MESSAGES/django.po b/apps/locale/en/LC_MESSAGES/django.po new file mode 100644 index 000000000..a460e176a --- /dev/null +++ b/apps/locale/en/LC_MESSAGES/django.po @@ -0,0 +1,9037 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-05-10 19:19+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: accounts/api/automations/base.py:79 tickets/api/ticket.py:132 +msgid "The parameter 'action' must be [{}]" +msgstr "" + +#: accounts/automations/change_secret/manager.py:225 +#, python-format +msgid "Success: %s, Failed: %s, Total: %s" +msgstr "" + +#: accounts/const/account.py:6 +#: accounts/serializers/automations/change_secret.py:34 +#: audits/signal_handlers/login_log.py:34 authentication/confirm/password.py:9 +#: authentication/confirm/password.py:24 authentication/confirm/password.py:26 +#: authentication/forms.py:28 +#: authentication/templates/authentication/login.html:329 +#: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 +#: settings/serializers/msg.py:35 terminal/serializers/storage.py:123 +#: terminal/serializers/storage.py:142 users/forms/profile.py:21 +#: users/serializers/user.py:110 +#: users/templates/users/_msg_user_created.html:13 +#: users/templates/users/user_password_verify.html:18 +#: xpack/plugins/cloud/serializers/account_attrs.py:28 +msgid "Password" +msgstr "" + +#: accounts/const/account.py:7 +#: accounts/serializers/automations/change_secret.py:35 +#: terminal/serializers/storage.py:124 +msgid "SSH key" +msgstr "" + +#: accounts/const/account.py:8 authentication/models/access_key.py:42 +msgid "Access key" +msgstr "" + +#: accounts/const/account.py:9 authentication/backends/passkey/models.py:16 +#: authentication/models/sso_token.py:14 settings/serializers/feature.py:52 +msgid "Token" +msgstr "" + +#: accounts/const/account.py:10 +msgid "API key" +msgstr "" + +#: accounts/const/account.py:14 common/db/fields.py:235 +#: settings/serializers/terminal.py:14 +msgid "All" +msgstr "" + +#: accounts/const/account.py:15 accounts/models/virtual.py:26 +msgid "Manual input" +msgstr "" + +#: accounts/const/account.py:16 +msgid "Dynamic user" +msgstr "" + +#: accounts/const/account.py:17 +msgid "Anonymous account" +msgstr "" + +#: accounts/const/account.py:18 +msgid "Specified account" +msgstr "" + +#: accounts/const/account.py:26 users/models/user.py:751 +msgid "Local" +msgstr "" + +#: accounts/const/account.py:27 +msgid "Collected" +msgstr "" + +#: accounts/const/account.py:28 accounts/serializers/account/account.py:28 +#: settings/serializers/auth/sms.py:79 +msgid "Template" +msgstr "" + +#: accounts/const/account.py:32 ops/const.py:46 +msgid "Skip" +msgstr "" + +#: accounts/const/account.py:33 audits/const.py:24 rbac/tree.py:239 +#: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 +msgid "Update" +msgstr "" + +#: accounts/const/account.py:34 accounts/const/automation.py:109 +#: accounts/serializers/automations/change_secret.py:164 audits/const.py:62 +#: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 +#: ops/const.py:76 terminal/const.py:79 xpack/plugins/cloud/const.py:46 +msgid "Failed" +msgstr "" + +#: accounts/const/automation.py:24 rbac/tree.py:52 +msgid "Push account" +msgstr "" + +#: accounts/const/automation.py:25 +msgid "Change secret" +msgstr "" + +#: accounts/const/automation.py:26 +msgid "Verify account" +msgstr "" + +#: accounts/const/automation.py:27 accounts/tasks/remove_account.py:24 +#: accounts/tasks/remove_account.py:33 +msgid "Remove account" +msgstr "" + +#: accounts/const/automation.py:28 +msgid "Gather accounts" +msgstr "" + +#: accounts/const/automation.py:29 +msgid "Verify gateway account" +msgstr "" + +#: accounts/const/automation.py:47 +msgid "Specific secret" +msgstr "" + +#: accounts/const/automation.py:48 +msgid "Random generate" +msgstr "" + +#: accounts/const/automation.py:52 ops/const.py:13 +msgid "Append SSH KEY" +msgstr "" + +#: accounts/const/automation.py:53 ops/const.py:14 +msgid "Empty and append SSH KEY" +msgstr "" + +#: accounts/const/automation.py:54 ops/const.py:15 +msgid "Replace (Replace only keys pushed by JumpServer) " +msgstr "" + +#: accounts/const/automation.py:59 +msgid "On asset create" +msgstr "" + +#: accounts/const/automation.py:62 +msgid "On perm add user" +msgstr "" + +#: accounts/const/automation.py:64 +msgid "On perm add user group" +msgstr "" + +#: accounts/const/automation.py:66 +msgid "On perm add asset" +msgstr "" + +#: accounts/const/automation.py:68 +msgid "On perm add node" +msgstr "" + +#: accounts/const/automation.py:70 +msgid "On perm add account" +msgstr "" + +#: accounts/const/automation.py:72 +msgid "On asset join node" +msgstr "" + +#: accounts/const/automation.py:74 +msgid "On user join group" +msgstr "" + +#: accounts/const/automation.py:82 +msgid "On perm change" +msgstr "" + +#: accounts/const/automation.py:89 +msgid "Inherit from group or node" +msgstr "" + +#: accounts/const/automation.py:97 +msgid "Create and push" +msgstr "" + +#: accounts/const/automation.py:98 +msgid "Only create" +msgstr "" + +#: accounts/const/automation.py:103 +#: authentication/serializers/password_mfa.py:16 +#: authentication/serializers/password_mfa.py:24 +#: notifications/backends/__init__.py:10 settings/serializers/msg.py:22 +#: settings/serializers/msg.py:64 users/forms/profile.py:100 +#: users/forms/profile.py:108 users/models/user.py:876 +#: users/templates/users/forgot_password.html:162 +#: users/views/profile/reset.py:94 +msgid "Email" +msgstr "" + +#: accounts/const/automation.py:105 terminal/const.py:87 +msgid "SFTP" +msgstr "" + +#: accounts/const/automation.py:110 +#: accounts/serializers/automations/change_secret.py:163 audits/const.py:61 +#: audits/models.py:64 audits/signal_handlers/activity_log.py:33 +#: common/const/choices.py:18 ops/const.py:74 ops/serializers/celery.py:48 +#: terminal/const.py:78 terminal/models/session/sharing.py:121 +#: tickets/views/approve.py:128 +msgid "Success" +msgstr "" + +#: accounts/const/automation.py:111 common/const/choices.py:16 +#: terminal/const.py:77 tickets/const.py:29 tickets/const.py:38 +msgid "Pending" +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 settings/serializers/feature.py:43 +msgid "HCP Vault" +msgstr "" + +#: accounts/mixins.py:35 +msgid "Export all" +msgstr "" + +#: accounts/mixins.py:37 +msgid "Export only selected items" +msgstr "" + +#: accounts/mixins.py:42 +#, python-format +msgid "Export filtered: %s" +msgstr "" + +#: accounts/mixins.py:48 +#, python-format +msgid "User %s view/export secret" +msgstr "" + +#: accounts/models/account.py:49 +#: accounts/models/automations/gather_account.py:16 +#: accounts/serializers/account/account.py:215 +#: accounts/serializers/account/account.py:260 +#: accounts/serializers/account/gathered_account.py:10 +#: accounts/serializers/automations/change_secret.py:108 +#: accounts/serializers/automations/change_secret.py:140 +#: accounts/templates/accounts/asset_account_change_info.html:7 +#: accounts/templates/accounts/change_secret_failed_info.html:11 +#: acls/serializers/base.py:123 assets/models/asset/common.py:95 +#: assets/models/asset/common.py:349 assets/models/cmd_filter.py:36 +#: audits/models.py:58 authentication/models/connection_token.py:36 +#: perms/models/asset_permission.py:69 terminal/backends/command/models.py:17 +#: terminal/models/session/session.py:32 terminal/notifications.py:155 +#: terminal/serializers/command.py:17 terminal/serializers/session.py:28 +#: terminal/templates/terminal/_msg_command_warning.html:4 +#: terminal/templates/terminal/_msg_session_sharing.html:4 +#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:256 +msgid "Asset" +msgstr "" + +#: accounts/models/account.py:53 accounts/models/template.py:16 +#: accounts/serializers/account/account.py:222 +#: accounts/serializers/account/account.py:270 +#: accounts/serializers/account/template.py:27 +#: authentication/serializers/connect_token_secret.py:50 +msgid "Su from" +msgstr "" + +#: accounts/models/account.py:55 assets/const/protocol.py:177 +#: settings/serializers/auth/cas.py:20 terminal/models/applet/applet.py:35 +#: terminal/models/virtualapp/virtualapp.py:21 +msgid "Version" +msgstr "" + +#: accounts/models/account.py:57 accounts/serializers/account/account.py:217 +#: users/models/user.py:928 +msgid "Source" +msgstr "" + +#: accounts/models/account.py:58 +msgid "Source ID" +msgstr "" + +#: accounts/models/account.py:61 +#: accounts/serializers/automations/change_secret.py:110 +#: accounts/serializers/automations/change_secret.py:141 +#: accounts/templates/accounts/change_secret_failed_info.html:12 +#: acls/serializers/base.py:124 acls/templates/acls/asset_login_reminder.html:7 +#: assets/serializers/gateway.py:28 audits/models.py:59 +#: authentication/api/connection_token.py:411 ops/models/base.py:18 +#: perms/models/asset_permission.py:75 settings/serializers/msg.py:33 +#: terminal/backends/command/models.py:18 terminal/models/session/session.py:34 +#: terminal/serializers/command.py:72 +#: terminal/templates/terminal/_msg_command_warning.html:8 +#: terminal/templates/terminal/_msg_session_sharing.html:8 +#: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:89 +msgid "Account" +msgstr "" + +#: accounts/models/account.py:67 +msgid "Can view asset account secret" +msgstr "" + +#: accounts/models/account.py:68 +msgid "Can view asset history account" +msgstr "" + +#: accounts/models/account.py:69 +msgid "Can view asset history account secret" +msgstr "" + +#: accounts/models/account.py:70 +msgid "Can verify account" +msgstr "" + +#: accounts/models/account.py:71 +msgid "Can push account" +msgstr "" + +#: accounts/models/account.py:72 +msgid "Can remove account" +msgstr "" + +#: accounts/models/automations/backup_account.py:27 +msgid "Backup type" +msgstr "" + +#: accounts/models/automations/backup_account.py:28 +#: accounts/models/automations/backup_account.py:29 +msgid "Password divided" +msgstr "" + +#: accounts/models/automations/backup_account.py:32 +msgid "Recipient part one" +msgstr "" + +#: accounts/models/automations/backup_account.py:36 +msgid "Recipient part two" +msgstr "" + +#: accounts/models/automations/backup_account.py:40 +msgid "Object storage recipient part one" +msgstr "" + +#: accounts/models/automations/backup_account.py:44 +msgid "Object storage recipient part two" +msgstr "" + +#: accounts/models/automations/backup_account.py:47 +msgid "Zip encrypt password" +msgstr "" + +#: accounts/models/automations/backup_account.py:56 +#: accounts/models/automations/backup_account.py:139 +msgid "Account backup plan" +msgstr "" + +#: accounts/models/automations/backup_account.py:120 +#: assets/models/automations/base.py:115 audits/models.py:65 +#: ops/models/base.py:55 ops/models/celery.py:88 ops/models/job.py:241 +#: ops/templates/ops/celery_task_log.html:75 +#: perms/models/asset_permission.py:78 +#: settings/templates/ldap/_msg_import_ldap_user.html:5 +#: terminal/models/applet/host.py:141 terminal/models/session/session.py:45 +#: tickets/models/ticket/apply_application.py:30 +#: tickets/models/ticket/apply_asset.py:19 +msgid "Date start" +msgstr "" + +#: accounts/models/automations/backup_account.py:123 +#: authentication/templates/authentication/_msg_oauth_bind.html:11 +#: notifications/notifications.py:186 +#: settings/templates/ldap/_msg_import_ldap_user.html:3 +msgid "Time" +msgstr "" + +#: accounts/models/automations/backup_account.py:127 +msgid "Account backup snapshot" +msgstr "" + +#: accounts/models/automations/backup_account.py:131 +#: accounts/serializers/account/backup.py:48 +#: accounts/serializers/automations/base.py:56 +#: assets/models/automations/base.py:122 +#: assets/serializers/automations/base.py:39 +msgid "Trigger mode" +msgstr "" + +#: accounts/models/automations/backup_account.py:134 audits/models.py:203 +#: terminal/models/session/sharing.py:125 xpack/plugins/cloud/models.py:208 +msgid "Reason" +msgstr "" + +#: accounts/models/automations/backup_account.py:136 +#: accounts/serializers/automations/change_secret.py:107 +#: accounts/serializers/automations/change_secret.py:142 +#: ops/serializers/job.py:74 terminal/serializers/session.py:52 +msgid "Is success" +msgstr "" + +#: accounts/models/automations/backup_account.py:144 +msgid "Account backup execution" +msgstr "" + +#: accounts/models/automations/base.py:18 +msgid "Account automation task" +msgstr "" + +#: accounts/models/automations/base.py:32 +msgid "Automation execution" +msgstr "" + +#: accounts/models/automations/base.py:33 +msgid "Automation executions" +msgstr "" + +#: accounts/models/automations/base.py:35 +msgid "Can view change secret execution" +msgstr "" + +#: accounts/models/automations/base.py:36 +msgid "Can add change secret execution" +msgstr "" + +#: accounts/models/automations/base.py:38 +msgid "Can view gather accounts execution" +msgstr "" + +#: accounts/models/automations/base.py:39 +msgid "Can add gather accounts execution" +msgstr "" + +#: accounts/models/automations/base.py:41 +msgid "Can view push account execution" +msgstr "" + +#: accounts/models/automations/base.py:42 +msgid "Can add push account execution" +msgstr "" + +#: accounts/models/automations/base.py:54 +msgid "SSH key change strategy" +msgstr "" + +#: accounts/models/automations/change_secret.py:15 +#: accounts/models/automations/gather_account.py:58 +#: accounts/serializers/account/backup.py:40 +#: accounts/serializers/automations/change_secret.py:58 +#: settings/serializers/auth/ldap.py:90 +msgid "Recipient" +msgstr "" + +#: accounts/models/automations/change_secret.py:22 +msgid "Change secret automation" +msgstr "" + +#: accounts/models/automations/change_secret.py:39 +msgid "Old secret" +msgstr "" + +#: accounts/models/automations/change_secret.py:40 +msgid "New secret" +msgstr "" + +#: accounts/models/automations/change_secret.py:41 +msgid "Date started" +msgstr "" + +#: accounts/models/automations/change_secret.py:42 +#: assets/models/automations/base.py:116 ops/models/base.py:56 +#: ops/models/celery.py:89 ops/models/job.py:242 +#: terminal/models/applet/host.py:142 +msgid "Date finished" +msgstr "" + +#: accounts/models/automations/change_secret.py:44 +#: assets/models/automations/base.py:113 audits/models.py:208 +#: audits/serializers.py:54 ops/models/base.py:49 ops/models/job.py:233 +#: terminal/models/applet/applet.py:320 terminal/models/applet/host.py:140 +#: terminal/models/component/status.py:30 +#: terminal/models/virtualapp/virtualapp.py:99 +#: terminal/serializers/applet.py:18 terminal/serializers/applet_host.py:136 +#: terminal/serializers/virtualapp.py:35 tickets/models/ticket/general.py:281 +#: tickets/serializers/super_ticket.py:13 +#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:204 +#: xpack/plugins/cloud/models.py:260 +msgid "Status" +msgstr "" + +#: accounts/models/automations/change_secret.py:47 +#: accounts/serializers/account/account.py:262 +#: accounts/templates/accounts/change_secret_failed_info.html:13 +#: assets/const/automation.py:8 +#: authentication/templates/authentication/passkey.html:173 +#: authentication/views/base.py:42 authentication/views/base.py:43 +#: authentication/views/base.py:44 common/const/choices.py:20 +#: settings/templates/ldap/_msg_import_ldap_user.html:26 +msgid "Error" +msgstr "" + +#: accounts/models/automations/change_secret.py:51 +msgid "Change secret record" +msgstr "" + +#: accounts/models/automations/gather_account.py:14 +msgid "Present" +msgstr "" + +#: accounts/models/automations/gather_account.py:15 +msgid "Date login" +msgstr "" + +#: accounts/models/automations/gather_account.py:17 +#: accounts/models/automations/push_account.py:15 accounts/models/base.py:65 +#: accounts/serializers/account/virtual.py:21 acls/serializers/base.py:19 +#: acls/serializers/base.py:50 audits/models.py:188 authentication/forms.py:21 +#: authentication/forms.py:23 authentication/models/temp_token.py:9 +#: authentication/templates/authentication/_msg_different_city.html:9 +#: authentication/templates/authentication/_msg_oauth_bind.html:9 +#: terminal/serializers/storage.py:136 users/forms/profile.py:31 +#: users/forms/profile.py:114 users/models/user.py:872 +#: users/templates/users/_msg_user_created.html:12 +#: xpack/plugins/cloud/serializers/account_attrs.py:26 +msgid "Username" +msgstr "" + +#: accounts/models/automations/gather_account.py:18 +msgid "Address login" +msgstr "" + +#: accounts/models/automations/gather_account.py:44 +msgid "Gather account automation" +msgstr "" + +#: accounts/models/automations/gather_account.py:56 +msgid "Is sync account" +msgstr "" + +#: accounts/models/automations/gather_account.py:75 +#: accounts/tasks/gather_accounts.py:29 +msgid "Gather asset accounts" +msgstr "" + +#: accounts/models/automations/push_account.py:14 +msgid "Triggers" +msgstr "" + +#: accounts/models/automations/push_account.py:16 acls/models/base.py:41 +#: acls/serializers/base.py:57 assets/models/cmd_filter.py:81 +#: audits/models.py:92 audits/serializers.py:84 +#: authentication/serializers/connect_token_secret.py:119 +#: authentication/templates/authentication/_access_key_modal.html:34 +#: tickets/serializers/ticket/ticket.py:21 +msgid "Action" +msgstr "" + +#: accounts/models/automations/push_account.py:57 +msgid "Push asset account" +msgstr "" + +#: accounts/models/automations/verify_account.py:15 +msgid "Verify asset account" +msgstr "" + +#: accounts/models/base.py:37 accounts/models/base.py:67 +#: accounts/serializers/account/account.py:442 +#: accounts/serializers/account/base.py:17 +#: accounts/serializers/automations/change_secret.py:47 +#: authentication/serializers/connect_token_secret.py:42 +#: authentication/serializers/connect_token_secret.py:51 +#: terminal/serializers/storage.py:140 +msgid "Secret type" +msgstr "" + +#: accounts/models/base.py:39 accounts/models/mixins/vault.py:49 +#: accounts/serializers/account/base.py:20 +#: authentication/models/temp_token.py:10 +#: authentication/templates/authentication/_access_key_modal.html:31 +#: settings/serializers/auth/radius.py:19 +msgid "Secret" +msgstr "" + +#: accounts/models/base.py:42 +#: accounts/serializers/automations/change_secret.py:41 +msgid "Secret strategy" +msgstr "" + +#: accounts/models/base.py:44 accounts/serializers/account/template.py:24 +#: accounts/serializers/automations/change_secret.py:46 +msgid "Password rules" +msgstr "" + +#: accounts/models/base.py:64 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 assets/models/asset/common.py:93 +#: assets/models/asset/common.py:159 assets/models/cmd_filter.py:21 +#: assets/models/domain.py:19 assets/models/label.py:18 +#: assets/models/platform.py:15 assets/models/platform.py:94 +#: assets/serializers/asset/common.py:149 assets/serializers/platform.py:143 +#: assets/serializers/platform.py:261 +#: authentication/backends/passkey/models.py:10 +#: authentication/serializers/connect_token_secret.py:113 +#: authentication/serializers/connect_token_secret.py:169 labels/models.py:11 +#: ops/mixin.py:21 ops/models/adhoc.py:20 ops/models/celery.py:15 +#: ops/models/celery.py:80 ops/models/job.py:142 ops/models/playbook.py:28 +#: ops/serializers/job.py:18 orgs/models.py:82 +#: perms/models/asset_permission.py:61 rbac/models/role.py:29 +#: settings/models.py:34 settings/models.py:183 settings/serializers/msg.py:89 +#: settings/serializers/terminal.py:9 terminal/models/applet/applet.py:33 +#: terminal/models/component/endpoint.py:12 +#: terminal/models/component/endpoint.py:109 +#: terminal/models/component/storage.py:26 terminal/models/component/task.py:13 +#: terminal/models/component/terminal.py:85 +#: terminal/models/virtualapp/provider.py:10 +#: terminal/models/virtualapp/virtualapp.py:19 tickets/api/ticket.py:87 +#: users/forms/profile.py:32 users/models/group.py:13 +#: users/models/preference.py:11 users/models/user.py:874 +#: xpack/plugins/cloud/models.py:32 xpack/plugins/cloud/models.py:276 +#: xpack/plugins/cloud/serializers/task.py:70 +msgid "Name" +msgstr "" + +#: accounts/models/base.py:69 +msgid "Privileged" +msgstr "" + +#: accounts/models/base.py:70 assets/models/asset/common.py:165 +#: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 +#: assets/models/label.py:22 +#: authentication/serializers/connect_token_secret.py:117 +#: terminal/models/applet/applet.py:40 +#: terminal/models/component/endpoint.py:120 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:180 +msgid "Is active" +msgstr "" + +#: accounts/models/template.py:18 +msgid "Auto push" +msgstr "" + +#: accounts/models/template.py:21 +msgid "Platforms" +msgstr "" + +#: accounts/models/template.py:23 +msgid "Push params" +msgstr "" + +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:333 +msgid "Account template" +msgstr "" + +#: accounts/models/template.py:31 +msgid "Can view asset account template secret" +msgstr "" + +#: accounts/models/template.py:32 +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 "" + +#: accounts/notifications.py:12 accounts/notifications.py:37 +msgid "Notification of account backup route task results" +msgstr "" + +#: accounts/notifications.py:22 accounts/notifications.py:46 +msgid "" +"{} - The account backup passage task has been completed. See the attachment " +"for details" +msgstr "" + +#: accounts/notifications.py:25 +msgid "" +"{} - The account backup passage task has been completed: the encryption " +"password has not been set - please go to personal information -> Basic file " +"encryption password for preference settings" +msgstr "" + +#: accounts/notifications.py:56 +msgid "Notification of implementation result of encryption change plan" +msgstr "" + +#: accounts/notifications.py:67 +msgid "" +"{} - The encryption change task has been completed. See the attachment for " +"details" +msgstr "" + +#: accounts/notifications.py:71 +msgid "" +"{} - The encryption change task has been completed: the encryption password " +"has not been set - please go to personal information -> set encryption " +"password in preferences" +msgstr "" + +#: accounts/notifications.py:83 +#: accounts/templates/accounts/asset_account_change_info.html:3 +msgid "Gather account change information" +msgstr "" + +#: accounts/notifications.py:105 +msgid "Change secret or push account failed information" +msgstr "" + +#: accounts/serializers/account/account.py:31 +msgid "Push now" +msgstr "" + +#: accounts/serializers/account/account.py:36 +msgid "Params" +msgstr "" + +#: accounts/serializers/account/account.py:40 +msgid "Exist policy" +msgstr "" + +#: accounts/serializers/account/account.py:195 assets/models/label.py:21 +#: assets/models/platform.py:95 assets/serializers/asset/common.py:125 +#: assets/serializers/cagegory.py:12 assets/serializers/platform.py:165 +#: assets/serializers/platform.py:262 perms/serializers/user_permission.py:26 +#: settings/models.py:36 tickets/models/ticket/apply_application.py:13 +#: users/models/preference.py:12 +msgid "Category" +msgstr "" + +#: accounts/serializers/account/account.py:196 +#: accounts/serializers/automations/base.py:55 acls/models/command_acl.py:24 +#: acls/serializers/command_acl.py:19 assets/models/automations/base.py:20 +#: assets/models/cmd_filter.py:74 assets/models/platform.py:96 +#: assets/serializers/asset/common.py:126 assets/serializers/platform.py:145 +#: assets/serializers/platform.py:164 audits/serializers.py:53 +#: audits/serializers.py:170 +#: authentication/serializers/connect_token_secret.py:126 ops/models/job.py:150 +#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:39 +#: terminal/models/component/storage.py:57 +#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29 +#: terminal/serializers/session.py:23 terminal/serializers/storage.py:264 +#: terminal/serializers/storage.py:276 tickets/models/comment.py:26 +#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16 +#: tickets/models/ticket/general.py:273 tickets/serializers/flow.py:53 +#: tickets/serializers/ticket/ticket.py:19 +msgid "Type" +msgstr "" + +#: accounts/serializers/account/account.py:211 +msgid "Asset not found" +msgstr "" + +#: accounts/serializers/account/account.py:251 +msgid "Has secret" +msgstr "" + +#: accounts/serializers/account/account.py:261 ops/models/celery.py:83 +#: tickets/models/comment.py:13 tickets/models/ticket/general.py:46 +#: tickets/models/ticket/general.py:277 tickets/serializers/super_ticket.py:14 +msgid "State" +msgstr "" + +#: accounts/serializers/account/account.py:263 +msgid "Changed" +msgstr "" + +#: accounts/serializers/account/account.py:273 +#: accounts/serializers/automations/base.py:22 acls/models/base.py:97 +#: acls/templates/acls/asset_login_reminder.html:6 +#: assets/models/automations/base.py:19 +#: assets/serializers/automations/base.py:20 +#: authentication/api/connection_token.py:410 ops/models/base.py:17 +#: ops/models/job.py:152 ops/serializers/job.py:19 +#: perms/serializers/permission.py:36 +#: terminal/templates/terminal/_msg_command_execute_alert.html:16 +msgid "Assets" +msgstr "" + +#: accounts/serializers/account/account.py:328 +msgid "Account already exists" +msgstr "" + +#: accounts/serializers/account/account.py:378 +#, python-format +msgid "Asset does not support this secret type: %s" +msgstr "" + +#: accounts/serializers/account/account.py:410 +msgid "Account has exist" +msgstr "" + +#: accounts/serializers/account/account.py:443 +#: authentication/serializers/connect_token_secret.py:159 +#: authentication/templates/authentication/_access_key_modal.html:30 +#: perms/models/perm_node.py:21 users/serializers/group.py:33 +msgid "ID" +msgstr "" + +#: accounts/serializers/account/account.py:453 acls/serializers/base.py:116 +#: acls/templates/acls/asset_login_reminder.html:5 +#: acls/templates/acls/user_login_reminder.html:5 +#: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:54 +#: audits/models.py:90 audits/models.py:172 audits/models.py:269 +#: audits/serializers.py:171 authentication/models/connection_token.py:32 +#: authentication/models/sso_token.py:16 +#: notifications/models/notification.py:12 +#: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:63 +#: rbac/builtin.py:124 rbac/models/rolebinding.py:49 +#: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 +#: terminal/models/session/session.py:30 terminal/models/session/sharing.py:34 +#: terminal/notifications.py:156 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:1062 +#: users/models/user.py:1100 +msgid "User" +msgstr "" + +#: accounts/serializers/account/account.py:454 +#: authentication/templates/authentication/_access_key_modal.html:33 +#: terminal/notifications.py:158 terminal/notifications.py:207 +msgid "Date" +msgstr "" + +#: accounts/serializers/account/backup.py:20 +msgid "Zip Encrypt Password" +msgstr "" + +#: accounts/serializers/account/backup.py:38 +#: accounts/serializers/automations/base.py:38 +msgid "Executions" +msgstr "" + +#: accounts/serializers/account/backup.py:41 +#: accounts/serializers/automations/change_secret.py:59 +msgid "Currently only mail sending is supported" +msgstr "" + +#: accounts/serializers/account/backup.py:43 +msgid "Asset type" +msgstr "" + +#: accounts/serializers/account/base.py:25 terminal/serializers/storage.py:149 +msgid "Passphrase" +msgstr "" + +#: accounts/serializers/account/base.py:78 +#: assets/serializers/asset/common.py:384 +msgid "Spec info" +msgstr "" + +#: accounts/serializers/account/base.py:80 +msgid "" +"Tip: If no username is required for authentication, fill in `null`, If AD " +"account, like `username@domain`" +msgstr "" + +#: accounts/serializers/account/template.py:13 +msgid "Password length" +msgstr "" + +#: accounts/serializers/account/template.py:14 +#: settings/serializers/security.py:44 +msgid "Lowercase" +msgstr "" + +#: accounts/serializers/account/template.py:15 +#: settings/serializers/security.py:41 +msgid "Uppercase" +msgstr "" + +#: accounts/serializers/account/template.py:16 +msgid "Digit" +msgstr "" + +#: accounts/serializers/account/template.py:17 +msgid "Special symbol" +msgstr "" + +#: accounts/serializers/account/template.py:19 +msgid "Exclude symbol" +msgstr "" + +#: accounts/serializers/account/template.py:38 +msgid "Secret generation strategy for account creation" +msgstr "" + +#: accounts/serializers/account/template.py:39 +msgid "Whether to automatically push the account to the asset" +msgstr "" + +#: accounts/serializers/account/template.py:42 +msgid "" +"Associated platform, you can configure push parameters. If not associated, " +"default parameters will be used" +msgstr "" + +#: accounts/serializers/account/virtual.py:19 assets/models/cmd_filter.py:40 +#: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:26 +#: ops/models/job.py:158 ops/models/playbook.py:31 rbac/models/role.py:37 +#: settings/models.py:39 terminal/models/applet/applet.py:45 +#: terminal/models/applet/applet.py:321 terminal/models/applet/host.py:143 +#: terminal/models/component/endpoint.py:25 +#: terminal/models/component/endpoint.py:119 +#: terminal/models/session/session.py:47 +#: terminal/models/virtualapp/virtualapp.py:28 tickets/models/comment.py:32 +#: tickets/models/ticket/general.py:295 users/models/user.py:910 +#: xpack/plugins/cloud/models.py:39 xpack/plugins/cloud/models.py:110 +msgid "Comment" +msgstr "" + +#: accounts/serializers/account/virtual.py:24 +msgid "" +"Current only support login from AD/LDAP. Secret priority: Same account in " +"asset secret > Login secret > Manual input.
For security, please set " +"config CACHE_LOGIN_PASSWORD_ENABLED to true" +msgstr "" + +#: accounts/serializers/automations/base.py:23 +#: assets/models/asset/common.py:164 assets/serializers/asset/common.py:152 +#: assets/serializers/automations/base.py:21 perms/serializers/permission.py:37 +msgid "Nodes" +msgstr "" + +#: accounts/serializers/automations/base.py:24 +msgid "Periodic perform" +msgstr "" + +#: accounts/serializers/automations/base.py:45 +msgid "Name already exists" +msgstr "" + +#: accounts/serializers/automations/base.py:54 +#: assets/models/automations/base.py:118 +#: assets/serializers/automations/base.py:38 +msgid "Automation snapshot" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:44 +msgid "SSH Key strategy" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:81 +msgid "* Please enter the correct password length" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:85 +msgid "* Password length range 6-30 bits" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:114 +#: assets/models/automations/base.py:127 +msgid "Automation task execution" +msgstr "" + +#: accounts/signal_handlers.py:47 +#, python-format +msgid "Push related accounts to assets: %s, by system" +msgstr "" + +#: accounts/signal_handlers.py:56 +#, python-format +msgid "Add account: %s" +msgstr "" + +#: accounts/signal_handlers.py:58 +#, python-format +msgid "Delete account: %s" +msgstr "" + +#: accounts/tasks/automation.py:25 +msgid "Account execute automation" +msgstr "" + +#: accounts/tasks/automation.py:51 accounts/tasks/automation.py:56 +msgid "Execute automation record" +msgstr "" + +#: accounts/tasks/backup_account.py:25 +msgid "Execute account backup plan" +msgstr "" + +#: accounts/tasks/gather_accounts.py:34 +msgid "Gather assets accounts" +msgstr "" + +#: accounts/tasks/push_account.py:15 accounts/tasks/push_account.py:23 +msgid "Push accounts to assets" +msgstr "" + +#: accounts/tasks/remove_account.py:44 +msgid "Clean historical accounts" +msgstr "" + +#: accounts/tasks/remove_account.py:76 +msgid "Remove historical accounts that are out of range." +msgstr "" + +#: accounts/tasks/template.py:11 +msgid "Template sync info to related accounts" +msgstr "" + +#: accounts/tasks/vault.py:31 +msgid "Sync secret to vault" +msgstr "" + +#: accounts/tasks/verify_account.py:49 +msgid "Verify asset account availability" +msgstr "" + +#: accounts/tasks/verify_account.py:55 +msgid "Verify accounts connectivity" +msgstr "" + +#: accounts/templates/accounts/asset_account_change_info.html:8 +msgid "Added account" +msgstr "" + +#: accounts/templates/accounts/asset_account_change_info.html:9 +msgid "Deleted account" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:3 +#: ops/templates/ops/celery_task_log.html:71 terminal/serializers/task.py:10 +msgid "Task name" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:4 +msgid "Task execution id" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:5 +#: acls/templates/acls/asset_login_reminder.html:3 +#: acls/templates/acls/user_login_reminder.html:3 +msgid "Respectful" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:6 +msgid "" +"Hello! The following is the failure of changing the password of your assets " +"or pushing the account. Please check and handle it in time." +msgstr "" + +#: accounts/utils.py:52 +msgid "" +"If the password starts with {{` and ends with }} `, then the password is not " +"allowed." +msgstr "" + +#: accounts/utils.py:59 +msgid "private key invalid or passphrase error" +msgstr "" + +#: acls/apps.py:7 +msgid "App Acls" +msgstr "" + +#: acls/const.py:6 audits/const.py:36 terminal/const.py:11 tickets/const.py:44 +#: tickets/templates/tickets/approve_check_password.html:47 +msgid "Reject" +msgstr "" + +#: acls/const.py:7 audits/const.py:33 terminal/const.py:9 +msgid "Accept" +msgstr "" + +#: acls/const.py:8 audits/const.py:34 +msgid "Review" +msgstr "" + +#: acls/const.py:9 +msgid "Warn" +msgstr "" + +#: acls/const.py:10 +msgid "Notify" +msgstr "" + +#: acls/models/base.py:37 assets/models/cmd_filter.py:76 +#: terminal/models/component/endpoint.py:112 xpack/plugins/cloud/models.py:282 +msgid "Priority" +msgstr "" + +#: acls/models/base.py:38 assets/models/cmd_filter.py:76 +#: terminal/models/component/endpoint.py:113 xpack/plugins/cloud/models.py:283 +msgid "1-100, the lower the value will be match first" +msgstr "" + +#: acls/models/base.py:42 assets/models/cmd_filter.py:86 +#: authentication/serializers/connect_token_secret.py:91 +msgid "Reviewers" +msgstr "" + +#: acls/models/base.py:43 authentication/models/access_key.py:25 +#: authentication/models/connection_token.py:53 +#: authentication/templates/authentication/_access_key_modal.html:32 +#: perms/models/asset_permission.py:82 terminal/models/session/sharing.py:29 +#: tickets/const.py:36 +msgid "Active" +msgstr "" + +#: acls/models/base.py:81 perms/serializers/permission.py:32 +#: users/models/preference.py:16 users/serializers/group.py:21 +#: users/serializers/user.py:311 +msgid "Users" +msgstr "" + +#: acls/models/base.py:98 assets/models/automations/base.py:17 +#: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:128 +#: perms/serializers/permission.py:45 perms/serializers/user_permission.py:75 +#: rbac/tree.py:35 +msgid "Accounts" +msgstr "" + +#: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 +#: ops/serializers/job.py:73 terminal/const.py:86 +#: terminal/models/session/session.py:43 terminal/serializers/command.py:18 +#: terminal/templates/terminal/_msg_command_alert.html:12 +#: terminal/templates/terminal/_msg_command_execute_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:23 +msgid "Command" +msgstr "" + +#: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 +#: xpack/plugins/cloud/models.py:299 +msgid "Regex" +msgstr "" + +#: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79 +#: settings/models.py:184 settings/serializers/feature.py:19 +#: settings/serializers/msg.py:78 xpack/plugins/license/models.py:30 +msgid "Content" +msgstr "" + +#: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79 +msgid "One line one command" +msgstr "" + +#: acls/models/command_acl.py:27 assets/models/cmd_filter.py:80 +msgid "Ignore case" +msgstr "" + +#: acls/models/command_acl.py:33 acls/models/command_acl.py:97 +#: acls/serializers/command_acl.py:29 +#: authentication/serializers/connect_token_secret.py:88 +#: terminal/templates/terminal/_msg_command_warning.html:14 +msgid "Command group" +msgstr "" + +#: acls/models/command_acl.py:86 +msgid "The generated regular expression is incorrect: {}" +msgstr "" + +#: acls/models/command_acl.py:103 +#: terminal/templates/terminal/_msg_command_warning.html:12 +msgid "Command acl" +msgstr "" + +#: acls/models/command_acl.py:112 tickets/const.py:12 +msgid "Command confirm" +msgstr "" + +#: acls/models/connect_method.py:10 +msgid "Connect methods" +msgstr "" + +#: acls/models/connect_method.py:13 +msgid "Connect method acl" +msgstr "" + +#: acls/models/login_acl.py:11 acls/models/login_asset_acl.py:9 +#: acls/serializers/login_acl.py:15 acls/serializers/login_asset_acl.py:13 +msgid "Rule" +msgstr "" + +#: acls/models/login_acl.py:14 +msgid "Login acl" +msgstr "" + +#: acls/models/login_acl.py:27 tickets/const.py:11 +msgid "Login confirm" +msgstr "" + +#: acls/models/login_asset_acl.py:12 +msgid "Login asset acl" +msgstr "" + +#: acls/models/login_asset_acl.py:22 tickets/const.py:13 +msgid "Login asset confirm" +msgstr "" + +#: acls/notifications.py:12 +msgid "User login reminder" +msgstr "" + +#: acls/notifications.py:42 +msgid "Asset login reminder" +msgstr "" + +#: acls/serializers/base.py:11 acls/serializers/login_acl.py:11 +msgid "With * indicating a match all. " +msgstr "" + +#: acls/serializers/base.py:26 +msgid "" +"With * indicating a match all. Such as: 192.168.10.1, 192.168.1.0/24, " +"10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 (Domain name " +"support)" +msgstr "" + +#: acls/serializers/base.py:41 assets/serializers/asset/host.py:19 +msgid "IP/Host" +msgstr "" + +#: acls/serializers/base.py:91 +msgid "Recipients" +msgstr "" + +#: acls/serializers/base.py:103 tickets/serializers/ticket/ticket.py:77 +msgid "The organization `{}` does not exist" +msgstr "" + +#: acls/serializers/base.py:109 +msgid "None of the reviewers belong to Organization `{}`" +msgstr "" + +#: acls/serializers/rules/rules.py:20 +#: xpack/plugins/cloud/serializers/task.py:145 +msgid "IP address invalid: `{}`" +msgstr "" + +#: acls/serializers/rules/rules.py:25 +msgid "" +"With * indicating a match all. Such as: 192.168.10.1, 192.168.1.0/24, " +"10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 " +msgstr "" + +#: acls/serializers/rules/rules.py:33 +#: authentication/templates/authentication/_msg_oauth_bind.html:12 +#: authentication/templates/authentication/_msg_rest_password_success.html:8 +#: authentication/templates/authentication/_msg_rest_public_key_success.html:8 +msgid "IP" +msgstr "" + +#: acls/serializers/rules/rules.py:35 +msgid "Time Period" +msgstr "" + +#: acls/templates/acls/asset_login_reminder.html:10 +msgid "" +"The user has just logged in to the asset. Please ensure that this is an " +"authorized operation. If you suspect that this is an unauthorized access, " +"please take appropriate measures immediately." +msgstr "" + +#: acls/templates/acls/asset_login_reminder.html:12 +#: acls/templates/acls/user_login_reminder.html:13 +msgid "Thank you" +msgstr "" + +#: acls/templates/acls/user_login_reminder.html:7 audits/models.py:194 +#: audits/models.py:263 +#: authentication/templates/authentication/_msg_different_city.html:11 +#: tickets/models/ticket/login_confirm.py:11 +msgid "Login city" +msgstr "" + +#: acls/templates/acls/user_login_reminder.html:8 audits/models.py:197 +#: audits/models.py:264 audits/serializers.py:68 +msgid "User agent" +msgstr "" + +#: acls/templates/acls/user_login_reminder.html:11 +msgid "" +"The user has just successfully logged into the system. Please ensure that " +"this is an authorized operation. If you suspect that this is an unauthorized " +"access, please take appropriate measures immediately." +msgstr "" + +#: assets/api/asset/asset.py:180 +msgid "Cannot create asset directly, you should create a host or other" +msgstr "" + +#: assets/api/domain.py:67 +msgid "Number required" +msgstr "" + +#: assets/api/node.py:58 +msgid "You can't update the root node name" +msgstr "" + +#: assets/api/node.py:65 +msgid "You can't delete the root node ({})" +msgstr "" + +#: assets/api/node.py:68 +msgid "Deletion failed and the node contains assets" +msgstr "" + +#: assets/api/tree.py:49 assets/serializers/node.py:42 +msgid "The same level node name cannot be the same" +msgstr "" + +#: assets/apps.py:9 +msgid "App Assets" +msgstr "" + +#: assets/automations/base/manager.py:191 +msgid "{} disabled" +msgstr "" + +#: assets/automations/base/manager.py:254 +msgid " - Platform {} ansible disabled" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:33 +#: authentication/models/connection_token.py:131 +msgid "No account" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:36 +msgid "Asset, {}, using account {}" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:55 +#, python-brace-format +msgid "Unable to connect to port {port} on {address}" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:58 +#: authentication/backends/oauth2/views.py:60 authentication/middleware.py:93 +#: xpack/plugins/cloud/providers/fc.py:47 +msgid "Authentication failed" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:60 +#: assets/automations/ping_gateway/manager.py:86 terminal/const.py:102 +msgid "Connect failed" +msgstr "" + +#: assets/const/automation.py:6 audits/const.py:6 audits/const.py:44 +#: audits/signal_handlers/activity_log.py:62 common/utils/ip/geoip/utils.py:31 +#: common/utils/ip/geoip/utils.py:37 common/utils/ip/utils.py:104 +msgid "Unknown" +msgstr "" + +#: assets/const/automation.py:7 +msgid "Ok" +msgstr "" + +#: assets/const/automation.py:12 +msgid "Ping" +msgstr "" + +#: assets/const/automation.py:13 +msgid "Ping gateway" +msgstr "" + +#: assets/const/automation.py:14 +msgid "Gather facts" +msgstr "" + +#: assets/const/base.py:32 audits/const.py:55 +#: terminal/serializers/applet_host.py:32 +msgid "Disabled" +msgstr "" + +#: assets/const/base.py:33 settings/serializers/basic.py:8 +#: users/serializers/preference/koko.py:19 +#: users/serializers/preference/lina.py:39 +#: users/serializers/preference/luna.py:77 +msgid "Basic" +msgstr "" + +#: assets/const/base.py:34 assets/const/protocol.py:268 +#: assets/models/asset/web.py:13 +msgid "Script" +msgstr "" + +#: assets/const/category.py:10 assets/models/asset/host.py:8 +#: settings/serializers/auth/radius.py:16 settings/serializers/auth/sms.py:71 +#: settings/serializers/feature.py:49 settings/serializers/msg.py:31 +#: terminal/models/component/endpoint.py:13 terminal/serializers/applet.py:17 +#: xpack/plugins/cloud/serializers/account_attrs.py:72 +msgid "Host" +msgstr "" + +#: assets/const/category.py:11 assets/models/asset/device.py:8 +msgid "Device" +msgstr "" + +#: assets/const/category.py:13 +msgid "Cloud service" +msgstr "" + +#: assets/const/category.py:14 assets/models/asset/gpt.py:11 +#: assets/models/asset/web.py:16 audits/const.py:42 +#: terminal/models/applet/applet.py:27 users/const.py:64 +msgid "Web" +msgstr "" + +#: assets/const/category.py:16 common/sdk/sms/endpoint.py:20 +msgid "Custom type" +msgstr "" + +#: assets/const/cloud.py:7 +msgid "Public cloud" +msgstr "" + +#: assets/const/cloud.py:8 +msgid "Private cloud" +msgstr "" + +#: assets/const/cloud.py:9 +msgid "Kubernetes" +msgstr "" + +#: assets/const/device.py:7 terminal/models/applet/applet.py:26 +#: tickets/const.py:9 +msgid "General" +msgstr "" + +#: assets/const/device.py:8 +msgid "Switch" +msgstr "" + +#: assets/const/device.py:9 +msgid "Router" +msgstr "" + +#: assets/const/device.py:10 +msgid "Firewall" +msgstr "" + +#: assets/const/gpt.py:7 +msgid "ChatGPT" +msgstr "" + +#: assets/const/host.py:12 rbac/tree.py:28 +msgid "Other" +msgstr "" + +#: assets/const/protocol.py:45 +msgid "Old SSH version" +msgstr "" + +#: assets/const/protocol.py:46 +msgid "Old SSH version like openssh 5.x or 6.x" +msgstr "" + +#: assets/const/protocol.py:57 +msgid "SFTP root" +msgstr "" + +#: assets/const/protocol.py:59 +#, python-brace-format +msgid "" +"SFTP root directory, Support variable:
- ${ACCOUNT} The connected " +"account username
- ${HOME} The home directory of the connected account " +"
- ${USER} The username of the user" +msgstr "" + +#: assets/const/protocol.py:74 +msgid "Console" +msgstr "" + +#: assets/const/protocol.py:75 +msgid "Connect to console session" +msgstr "" + +#: assets/const/protocol.py:79 +msgid "Any" +msgstr "" + +#: assets/const/protocol.py:81 settings/serializers/security.py:232 +msgid "Security" +msgstr "" + +#: assets/const/protocol.py:82 +msgid "Security layer to use for the connection" +msgstr "" + +#: assets/const/protocol.py:88 +msgid "AD domain" +msgstr "" + +#: assets/const/protocol.py:103 +msgid "Username prompt" +msgstr "" + +#: assets/const/protocol.py:104 +msgid "We will send username when we see this prompt" +msgstr "" + +#: assets/const/protocol.py:109 +msgid "Password prompt" +msgstr "" + +#: assets/const/protocol.py:110 +msgid "We will send password when we see this prompt" +msgstr "" + +#: assets/const/protocol.py:115 +msgid "Success prompt" +msgstr "" + +#: assets/const/protocol.py:116 +msgid "We will consider login success when we see this prompt" +msgstr "" + +#: assets/const/protocol.py:127 assets/models/asset/database.py:10 +#: settings/serializers/msg.py:47 +msgid "Use SSL" +msgstr "" + +#: assets/const/protocol.py:162 +msgid "SYSDBA" +msgstr "" + +#: assets/const/protocol.py:163 +msgid "Connect as SYSDBA" +msgstr "" + +#: assets/const/protocol.py:178 +msgid "" +"SQL Server version, Different versions have different connection drivers" +msgstr "" + +#: assets/const/protocol.py:202 +msgid "Auth source" +msgstr "" + +#: assets/const/protocol.py:203 +msgid "The database to authenticate against" +msgstr "" + +#: assets/const/protocol.py:215 +msgid "Auth username" +msgstr "" + +#: assets/const/protocol.py:238 +msgid "Safe mode" +msgstr "" + +#: assets/const/protocol.py:240 +msgid "" +"When safe mode is enabled, some operations will be disabled, such as: New " +"tab, right click, visit other website, etc." +msgstr "" + +#: assets/const/protocol.py:245 assets/models/asset/web.py:9 +#: assets/serializers/asset/info/spec.py:16 +msgid "Autofill" +msgstr "" + +#: assets/const/protocol.py:253 assets/models/asset/web.py:10 +msgid "Username selector" +msgstr "" + +#: assets/const/protocol.py:258 assets/models/asset/web.py:11 +msgid "Password selector" +msgstr "" + +#: assets/const/protocol.py:263 assets/models/asset/web.py:12 +msgid "Submit selector" +msgstr "" + +#: assets/const/protocol.py:286 +msgid "API mode" +msgstr "" + +#: assets/const/types.py:251 +msgid "All types" +msgstr "" + +#: assets/const/web.py:7 +msgid "Website" +msgstr "" + +#: assets/exceptions.py:12 +msgid "This function is not supported temporarily" +msgstr "" + +#: assets/models/asset/cloud.py:11 +msgid "Cloud" +msgstr "" + +#: assets/models/asset/common.py:94 assets/models/platform.py:16 +#: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:72 +#: settings/serializers/msg.py:32 terminal/serializers/storage.py:133 +#: xpack/plugins/cloud/serializers/account_attrs.py:73 +msgid "Port" +msgstr "" + +#: assets/models/asset/common.py:160 assets/serializers/asset/common.py:150 +#: settings/serializers/terminal.py:10 +msgid "Address" +msgstr "" + +#: assets/models/asset/common.py:161 assets/models/platform.py:134 +#: authentication/backends/passkey/models.py:12 +#: authentication/serializers/connect_token_secret.py:118 +#: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:329 +msgid "Platform" +msgstr "" + +#: assets/models/asset/common.py:163 +#: authentication/serializers/connect_token_secret.py:136 +#: perms/serializers/user_permission.py:28 xpack/plugins/cloud/models.py:331 +msgid "Domain" +msgstr "" + +#: assets/models/asset/common.py:166 assets/serializers/asset/common.py:385 +#: assets/serializers/asset/host.py:11 +msgid "Gathered info" +msgstr "" + +#: assets/models/asset/common.py:167 assets/serializers/asset/custom.py:14 +msgid "Custom info" +msgstr "" + +#: assets/models/asset/common.py:352 +msgid "Can refresh asset hardware info" +msgstr "" + +#: assets/models/asset/common.py:353 +msgid "Can test asset connectivity" +msgstr "" + +#: assets/models/asset/common.py:354 +msgid "Can match asset" +msgstr "" + +#: assets/models/asset/common.py:355 +msgid "Can change asset nodes" +msgstr "" + +#: assets/models/asset/custom.py:8 +msgid "Custom asset" +msgstr "" + +#: assets/models/asset/database.py:11 +msgid "CA cert" +msgstr "" + +#: assets/models/asset/database.py:12 +msgid "Client cert" +msgstr "" + +#: assets/models/asset/database.py:13 +msgid "Client key" +msgstr "" + +#: assets/models/asset/database.py:14 +msgid "Allow invalid cert" +msgstr "" + +#: assets/models/asset/gpt.py:8 settings/serializers/feature.py:84 +msgid "Proxy" +msgstr "" + +#: assets/models/automations/base.py:18 assets/models/cmd_filter.py:32 +#: assets/models/node.py:553 perms/models/asset_permission.py:72 +#: tickets/models/ticket/apply_asset.py:14 xpack/plugins/cloud/models.py:330 +msgid "Node" +msgstr "" + +#: assets/models/automations/base.py:22 ops/models/job.py:236 +#: settings/serializers/auth/sms.py:103 +msgid "Parameters" +msgstr "" + +#: assets/models/automations/base.py:29 assets/models/automations/base.py:111 +msgid "Automation task" +msgstr "" + +#: assets/models/automations/base.py:104 +msgid "Asset automation task" +msgstr "" + +#: assets/models/automations/base.py:114 assets/models/cmd_filter.py:41 +#: audits/models.py:267 common/db/models.py:34 ops/models/base.py:54 +#: ops/models/job.py:240 users/models/user.py:1101 +msgid "Date created" +msgstr "" + +#: assets/models/automations/gather_facts.py:15 +msgid "Gather asset facts" +msgstr "" + +#: assets/models/automations/ping.py:15 +msgid "Ping asset" +msgstr "" + +#: assets/models/base.py:19 terminal/notifications.py:225 +msgid "Connectivity" +msgstr "" + +#: assets/models/base.py:21 authentication/models/temp_token.py:12 +msgid "Date verified" +msgstr "" + +#: assets/models/cmd_filter.py:28 perms/models/asset_permission.py:66 +#: users/models/group.py:25 users/models/user.py:880 +msgid "User group" +msgstr "" + +#: assets/models/cmd_filter.py:42 common/db/models.py:35 +#: users/models/user.py:936 +msgid "Date updated" +msgstr "" + +#: assets/models/cmd_filter.py:44 assets/models/cmd_filter.py:91 +#: common/db/models.py:32 users/models/user.py:917 +#: users/serializers/group.py:32 +msgid "Created by" +msgstr "" + +#: assets/models/cmd_filter.py:52 +msgid "Command filter" +msgstr "" + +#: assets/models/cmd_filter.py:66 +msgid "Deny" +msgstr "" + +#: assets/models/cmd_filter.py:67 +msgid "Allow" +msgstr "" + +#: assets/models/cmd_filter.py:68 +msgid "Reconfirm" +msgstr "" + +#: assets/models/cmd_filter.py:72 +msgid "Filter" +msgstr "" + +#: assets/models/cmd_filter.py:95 +msgid "Command filter rule" +msgstr "" + +#: assets/models/domain.py:22 +msgid "Zone" +msgstr "" + +#: assets/models/favorite_asset.py:17 +msgid "Favorite asset" +msgstr "" + +#: assets/models/gateway.py:34 assets/serializers/domain.py:19 +msgid "Gateway" +msgstr "" + +#: assets/models/label.py:15 rbac/const.py:6 users/models/user.py:1086 +msgid "System" +msgstr "" + +#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 +#: assets/serializers/cagegory.py:24 +#: authentication/models/connection_token.py:29 +#: authentication/serializers/connect_token_secret.py:125 +#: common/serializers/common.py:86 labels/models.py:12 settings/models.py:35 +#: users/models/preference.py:13 +msgid "Value" +msgstr "" + +#: assets/models/label.py:40 assets/serializers/cagegory.py:10 +#: assets/serializers/cagegory.py:17 assets/serializers/cagegory.py:23 +#: assets/serializers/platform.py:144 +#: authentication/serializers/connect_token_secret.py:124 +#: common/serializers/common.py:85 labels/models.py:17 labels/models.py:33 +#: labels/serializers.py:45 settings/serializers/msg.py:90 +msgid "Label" +msgstr "" + +#: assets/models/node.py:169 +msgid "New node" +msgstr "" + +#: assets/models/node.py:467 audits/backends/db.py:65 audits/backends/db.py:66 +msgid "empty" +msgstr "" + +#: assets/models/node.py:538 perms/models/perm_node.py:28 +msgid "Key" +msgstr "" + +#: assets/models/node.py:540 assets/serializers/node.py:20 +msgid "Full value" +msgstr "" + +#: assets/models/node.py:544 perms/models/perm_node.py:30 +msgid "Parent key" +msgstr "" + +#: assets/models/node.py:556 +msgid "Can match node" +msgstr "" + +#: assets/models/platform.py:17 +msgid "Primary" +msgstr "" + +#: assets/models/platform.py:18 +msgid "Required" +msgstr "" + +#: assets/models/platform.py:19 assets/serializers/platform.py:146 +#: xpack/plugins/cloud/providers/nutanix.py:30 +msgid "Default" +msgstr "" + +#: assets/models/platform.py:20 +msgid "Public" +msgstr "" + +#: assets/models/platform.py:21 assets/serializers/platform.py:74 +#: settings/serializers/settings.py:95 +#: users/templates/users/reset_password.html:29 +msgid "Setting" +msgstr "" + +#: assets/models/platform.py:38 audits/const.py:56 +#: authentication/backends/passkey/models.py:11 settings/models.py:38 +#: terminal/serializers/applet_host.py:33 +msgid "Enabled" +msgstr "" + +#: assets/models/platform.py:39 +msgid "Ansible config" +msgstr "" + +#: assets/models/platform.py:41 assets/serializers/platform.py:33 +msgid "Ping enabled" +msgstr "" + +#: assets/models/platform.py:42 assets/serializers/platform.py:34 +msgid "Ping method" +msgstr "" + +#: assets/models/platform.py:43 +msgid "Ping params" +msgstr "" + +#: assets/models/platform.py:45 assets/models/platform.py:69 +#: assets/serializers/platform.py:36 +msgid "Gather facts enabled" +msgstr "" + +#: assets/models/platform.py:47 assets/models/platform.py:71 +#: assets/serializers/platform.py:40 +msgid "Gather facts method" +msgstr "" + +#: assets/models/platform.py:49 assets/models/platform.py:73 +msgid "Gather facts params" +msgstr "" + +#: assets/models/platform.py:51 assets/serializers/platform.py:50 +msgid "Change secret enabled" +msgstr "" + +#: assets/models/platform.py:53 assets/serializers/platform.py:54 +msgid "Change secret method" +msgstr "" + +#: assets/models/platform.py:55 +msgid "Change secret params" +msgstr "" + +#: assets/models/platform.py:57 assets/serializers/platform.py:57 +msgid "Push account enabled" +msgstr "" + +#: assets/models/platform.py:59 assets/serializers/platform.py:61 +msgid "Push account method" +msgstr "" + +#: assets/models/platform.py:61 +msgid "Push account params" +msgstr "" + +#: assets/models/platform.py:63 assets/serializers/platform.py:43 +msgid "Verify account enabled" +msgstr "" + +#: assets/models/platform.py:65 assets/serializers/platform.py:47 +msgid "Verify account method" +msgstr "" + +#: assets/models/platform.py:67 +msgid "Verify account params" +msgstr "" + +#: assets/models/platform.py:75 +msgid "Remove account enabled" +msgstr "" + +#: assets/models/platform.py:77 +msgid "Remove account method" +msgstr "" + +#: assets/models/platform.py:79 +msgid "Remove account params" +msgstr "" + +#: assets/models/platform.py:97 tickets/models/ticket/general.py:298 +msgid "Meta" +msgstr "" + +#: assets/models/platform.py:98 labels/models.py:13 +msgid "Internal" +msgstr "" + +#: assets/models/platform.py:102 assets/serializers/platform.py:163 +msgid "Charset" +msgstr "" + +#: assets/models/platform.py:104 assets/serializers/platform.py:198 +msgid "Domain enabled" +msgstr "" + +#: assets/models/platform.py:106 assets/serializers/platform.py:191 +msgid "Su enabled" +msgstr "" + +#: assets/models/platform.py:107 assets/serializers/platform.py:169 +msgid "Su method" +msgstr "" + +#: assets/models/platform.py:108 assets/serializers/platform.py:172 +msgid "Custom fields" +msgstr "" + +#: assets/models/utils.py:18 +#, python-format +msgid "%(value)s is not an even number" +msgstr "" + +#: assets/notifications.py:12 +msgid "" +"Batch update platform in assets, skipping assets that do not meet platform " +"type" +msgstr "" + +#: assets/serializers/asset/common.py:127 assets/serializers/platform.py:166 +#: authentication/serializers/connect_token_secret.py:30 +#: authentication/serializers/connect_token_secret.py:75 +#: perms/models/asset_permission.py:76 perms/serializers/permission.py:46 +#: perms/serializers/user_permission.py:74 xpack/plugins/cloud/models.py:332 +#: xpack/plugins/cloud/serializers/task.py:33 +msgid "Protocols" +msgstr "" + +#: assets/serializers/asset/common.py:129 +#: assets/serializers/asset/common.py:151 +msgid "Node path" +msgstr "" + +#: assets/serializers/asset/common.py:148 +#: assets/serializers/asset/common.py:386 +msgid "Auto info" +msgstr "" + +#: assets/serializers/asset/common.py:245 +msgid "Platform not exist" +msgstr "" + +#: assets/serializers/asset/common.py:281 +msgid "port out of range (0-65535)" +msgstr "" + +#: assets/serializers/asset/common.py:288 +msgid "Protocol is required: {}" +msgstr "" + +#: assets/serializers/asset/common.py:316 +msgid "Invalid data" +msgstr "" + +#: assets/serializers/asset/database.py:13 +msgid "Default database" +msgstr "" + +#: assets/serializers/asset/gpt.py:20 +msgid "" +"If the server cannot directly connect to the API address, you need set up an " +"HTTP proxy. e.g. http(s)://host:port" +msgstr "" + +#: assets/serializers/asset/gpt.py:24 +msgid "HTTP proxy" +msgstr "" + +#: assets/serializers/asset/gpt.py:31 +msgid "Proxy must start with http:// or https://" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:6 +msgid "Vendor" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:7 +msgid "Model" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:8 +#: tickets/models/ticket/general.py:297 +msgid "Serial number" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:9 +msgid "CPU model" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:10 +msgid "CPU count" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:11 +msgid "CPU cores" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:12 +msgid "CPU vcpus" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:13 +msgid "Memory" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:14 +msgid "Disk total" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:16 +#: authentication/serializers/connect_token_secret.py:115 +msgid "OS" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:17 +msgid "OS version" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:18 +msgid "OS arch" +msgstr "" + +#: assets/serializers/cagegory.py:13 +msgid "Constraints" +msgstr "" + +#: assets/serializers/cagegory.py:19 +msgid "Types" +msgstr "" + +#: assets/serializers/domain.py:21 orgs/serializers.py:13 +#: perms/serializers/permission.py:40 +msgid "Assets amount" +msgstr "" + +#: assets/serializers/gateway.py:23 common/validators.py:34 +msgid "This field must be unique." +msgstr "" + +#: assets/serializers/node.py:17 +msgid "value" +msgstr "" + +#: assets/serializers/node.py:31 +msgid "Can't contains: /" +msgstr "" + +#: assets/serializers/platform.py:33 +msgid "Enable asset detection" +msgstr "" + +#: assets/serializers/platform.py:37 +msgid "Enable asset information collection" +msgstr "" + +#: assets/serializers/platform.py:44 +msgid "Enable account verification" +msgstr "" + +#: assets/serializers/platform.py:51 +msgid "Enable account secret auto change" +msgstr "" + +#: assets/serializers/platform.py:58 +msgid "Enable account auto push" +msgstr "" + +#: assets/serializers/platform.py:64 +msgid "Gather accounts enabled" +msgstr "" + +#: assets/serializers/platform.py:65 +msgid "Enable account collection" +msgstr "" + +#: assets/serializers/platform.py:68 +msgid "Gather accounts method" +msgstr "" + +#: assets/serializers/platform.py:75 +msgid "Port from addr" +msgstr "" + +#: assets/serializers/platform.py:87 +msgid "" +"This protocol is primary, and it must be set when adding assets. " +"Additionally, there can only be one primary protocol." +msgstr "" + +#: assets/serializers/platform.py:92 +msgid "This protocol is required, and it must be set when adding assets." +msgstr "" + +#: assets/serializers/platform.py:95 +msgid "" +"This protocol is default, when adding assets, it will be displayed by " +"default." +msgstr "" + +#: assets/serializers/platform.py:98 +msgid "This protocol is public, asset will show this protocol to user" +msgstr "" + +#: assets/serializers/platform.py:147 +msgid "Help text" +msgstr "" + +#: assets/serializers/platform.py:148 +msgid "Choices" +msgstr "" + +#: assets/serializers/platform.py:167 +msgid "Automation" +msgstr "" + +#: assets/serializers/platform.py:193 +msgid "" +"Login with account when accessing assets, then automatically switch to " +"another, similar to logging in with a regular account and then switching to " +"root" +msgstr "" + +#: assets/serializers/platform.py:199 +msgid "Assets can be connected using a domain gateway" +msgstr "" + +#: assets/serializers/platform.py:201 +msgid "Default Domain" +msgstr "" + +#: assets/serializers/platform.py:222 +msgid "type is required" +msgstr "" + +#: assets/serializers/platform.py:237 +msgid "Protocols is required" +msgstr "" + +#: assets/signal_handlers/asset.py:26 assets/tasks/ping.py:35 +msgid "Test assets connectivity " +msgstr "" + +#: assets/signal_handlers/asset.py:36 +msgid "Gather asset hardware info" +msgstr "" + +#: assets/tasks/automation.py:24 +msgid "Asset execute automation" +msgstr "" + +#: assets/tasks/gather_facts.py:21 assets/tasks/gather_facts.py:27 +msgid "Gather assets facts" +msgstr "" + +#: assets/tasks/gather_facts.py:39 +msgid "Update assets hardware info: " +msgstr "" + +#: assets/tasks/gather_facts.py:47 +msgid "Update node asset hardware information: " +msgstr "" + +#: assets/tasks/nodes_amount.py:16 +msgid "Check the amount of assets under the node" +msgstr "" + +#: assets/tasks/nodes_amount.py:28 +msgid "" +"The task of self-checking is already running and cannot be started repeatedly" +msgstr "" + +#: assets/tasks/nodes_amount.py:33 +msgid "Periodic check the amount of assets under the node" +msgstr "" + +#: assets/tasks/ping.py:20 assets/tasks/ping.py:26 +msgid "Test assets connectivity" +msgstr "" + +#: assets/tasks/ping.py:42 +msgid "Test if the assets under the node are connectable " +msgstr "" + +#: assets/tasks/ping_gateway.py:19 assets/tasks/ping_gateway.py:25 +#: assets/tasks/ping_gateway.py:34 +msgid "Test gateways connectivity" +msgstr "" + +#: assets/tasks/utils.py:16 +msgid "Asset has been disabled, skipped: {}" +msgstr "" + +#: assets/tasks/utils.py:20 +msgid "Asset may not be support ansible, skipped: {}" +msgstr "" + +#: assets/tasks/utils.py:38 +msgid "For security, do not push user {}" +msgstr "" + +#: assets/tasks/utils.py:54 +msgid "No assets matched, stop task" +msgstr "" + +#: audits/apps.py:9 +msgid "App Audits" +msgstr "" + +#: audits/backends/db.py:16 +msgid "The text content is too long. Use Elasticsearch to store operation logs" +msgstr "" + +#: audits/backends/db.py:91 +msgid "Tips" +msgstr "" + +#: audits/const.py:12 +msgid "Mkdir" +msgstr "" + +#: audits/const.py:13 +msgid "Rmdir" +msgstr "" + +#: audits/const.py:14 audits/const.py:25 +#: authentication/templates/authentication/_access_key_modal.html:65 +#: rbac/tree.py:240 +msgid "Delete" +msgstr "" + +#: audits/const.py:15 +msgid "Upload" +msgstr "" + +#: audits/const.py:16 +msgid "Rename" +msgstr "" + +#: audits/const.py:17 +msgid "Symlink" +msgstr "" + +#: audits/const.py:18 audits/const.py:28 terminal/api/session/session.py:149 +msgid "Download" +msgstr "" + +#: audits/const.py:19 +msgid "Rename dir" +msgstr "" + +#: audits/const.py:23 rbac/tree.py:238 terminal/api/session/session.py:277 +#: terminal/templates/terminal/_msg_command_warning.html:18 +#: terminal/templates/terminal/_msg_session_sharing.html:10 +msgid "View" +msgstr "" + +#: audits/const.py:26 +#: authentication/templates/authentication/_access_key_modal.html:22 +#: rbac/tree.py:237 +msgid "Create" +msgstr "" + +#: audits/const.py:29 +msgid "Connect" +msgstr "" + +#: audits/const.py:30 authentication/templates/authentication/login.html:296 +#: authentication/templates/authentication/login.html:368 +#: templates/_header_bar.html:101 +msgid "Login" +msgstr "" + +#: audits/const.py:31 ops/const.py:9 +msgid "Change password" +msgstr "" + +#: audits/const.py:35 +msgid "Notifications" +msgstr "" + +#: audits/const.py:37 tickets/const.py:45 +msgid "Approve" +msgstr "" + +#: audits/const.py:38 +#: authentication/templates/authentication/_access_key_modal.html:155 +#: authentication/templates/authentication/_mfa_confirm_modal.html:53 +#: templates/_modal.html:22 tickets/const.py:43 +msgid "Close" +msgstr "" + +#: audits/const.py:43 settings/serializers/terminal.py:6 +#: terminal/models/applet/host.py:26 terminal/models/component/terminal.py:175 +#: terminal/models/virtualapp/provider.py:14 terminal/serializers/session.py:55 +#: terminal/serializers/session.py:69 +msgid "Terminal" +msgstr "" + +#: audits/const.py:48 audits/models.py:132 +msgid "Operate log" +msgstr "" + +#: audits/const.py:49 +msgid "Session log" +msgstr "" + +#: audits/const.py:50 +msgid "Login log" +msgstr "" + +#: audits/const.py:51 terminal/models/applet/host.py:144 +#: terminal/models/component/task.py:22 +msgid "Task" +msgstr "" + +#: audits/const.py:57 +msgid "-" +msgstr "" + +#: audits/handler.py:116 +msgid "Yes" +msgstr "" + +#: audits/handler.py:116 +msgid "No" +msgstr "" + +#: audits/models.py:47 +msgid "Job audit log" +msgstr "" + +#: audits/models.py:56 audits/models.py:100 audits/models.py:175 +#: terminal/models/session/session.py:39 terminal/models/session/sharing.py:113 +msgid "Remote addr" +msgstr "" + +#: audits/models.py:61 audits/serializers.py:38 +msgid "Operate" +msgstr "" + +#: audits/models.py:63 +msgid "Filename" +msgstr "" + +#: audits/models.py:66 common/serializers/common.py:98 +msgid "File" +msgstr "" + +#: audits/models.py:67 terminal/backends/command/models.py:21 +#: terminal/models/session/replay.py:9 terminal/models/session/sharing.py:20 +#: terminal/models/session/sharing.py:95 +#: terminal/templates/terminal/_msg_command_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:17 +#: tickets/models/ticket/command_confirm.py:15 +msgid "Session" +msgstr "" + +#: audits/models.py:70 +msgid "File transfer log" +msgstr "" + +#: audits/models.py:94 audits/serializers.py:86 +msgid "Resource Type" +msgstr "" + +#: audits/models.py:95 audits/models.py:98 audits/models.py:144 +#: audits/serializers.py:85 labels/serializers.py:46 +msgid "Resource" +msgstr "" + +#: audits/models.py:101 audits/models.py:147 audits/models.py:177 +#: terminal/serializers/command.py:75 +msgid "Datetime" +msgstr "" + +#: audits/models.py:140 +msgid "Activity type" +msgstr "" + +#: audits/models.py:150 +msgid "Detail" +msgstr "" + +#: audits/models.py:153 +msgid "Detail ID" +msgstr "" + +#: audits/models.py:157 +msgid "Activity log" +msgstr "" + +#: audits/models.py:173 +msgid "Change by" +msgstr "" + +#: audits/models.py:183 +msgid "Password change log" +msgstr "" + +#: audits/models.py:190 audits/models.py:265 +msgid "Login type" +msgstr "" + +#: audits/models.py:192 audits/models.py:261 +#: tickets/models/ticket/login_confirm.py:10 +msgid "Login IP" +msgstr "" + +#: audits/models.py:200 audits/serializers.py:52 +#: authentication/templates/authentication/_mfa_confirm_modal.html:14 +#: users/forms/profile.py:63 users/models/user.py:897 +#: users/serializers/profile.py:102 +msgid "MFA" +msgstr "" + +#: audits/models.py:210 +#: authentication/templates/authentication/_msg_different_city.html:10 +#: tickets/models/ticket/login_confirm.py:12 +msgid "Login Date" +msgstr "" + +#: audits/models.py:212 audits/models.py:266 +msgid "Auth backend" +msgstr "" + +#: audits/models.py:256 +msgid "User login log" +msgstr "" + +#: audits/models.py:262 +msgid "Session key" +msgstr "" + +#: audits/models.py:298 +msgid "User session" +msgstr "" + +#: audits/models.py:300 +msgid "Offline user session" +msgstr "" + +#: audits/serializers.py:33 ops/models/adhoc.py:25 ops/models/base.py:16 +#: ops/models/base.py:53 ops/models/celery.py:86 ops/models/job.py:151 +#: ops/models/job.py:239 ops/models/playbook.py:30 +#: terminal/models/session/sharing.py:25 +msgid "Creator" +msgstr "" + +#: audits/serializers.py:69 +msgid "Reason display" +msgstr "" + +#: audits/serializers.py:70 audits/serializers.py:184 +msgid "Auth backend display" +msgstr "" + +#: audits/serializers.py:134 +#, python-format +msgid "%s %s this resource" +msgstr "" + +#: audits/serializers.py:172 authentication/models/connection_token.py:47 +#: authentication/models/temp_token.py:13 perms/models/asset_permission.py:80 +#: tickets/models/ticket/apply_application.py:31 +#: tickets/models/ticket/apply_asset.py:20 users/models/user.py:915 +msgid "Date expired" +msgstr "" + +#: audits/signal_handlers/activity_log.py:26 +#, python-format +msgid "User %s use account %s login asset %s" +msgstr "" + +#: audits/signal_handlers/activity_log.py:34 +#, python-format +msgid "User %s login system %s" +msgstr "" + +#: audits/signal_handlers/activity_log.py:64 +#, python-format +msgid "User %s perform a task for this resource: %s" +msgstr "" + +#: audits/signal_handlers/login_log.py:33 +msgid "SSH Key" +msgstr "" + +#: audits/signal_handlers/login_log.py:35 settings/serializers/auth/sso.py:13 +msgid "SSO" +msgstr "" + +#: audits/signal_handlers/login_log.py:36 +msgid "Auth Token" +msgstr "" + +#: audits/signal_handlers/login_log.py:37 authentication/notifications.py:73 +#: authentication/views/login.py:77 notifications/backends/__init__.py:11 +#: settings/serializers/auth/wecom.py:10 settings/serializers/auth/wecom.py:15 +#: users/models/user.py:758 users/models/user.py:930 +msgid "WeCom" +msgstr "" + +#: audits/signal_handlers/login_log.py:38 authentication/views/feishu.py:105 +#: authentication/views/login.py:89 notifications/backends/__init__.py:14 +#: settings/serializers/auth/feishu.py:10 users/models/user.py:760 +#: users/models/user.py:932 +msgid "FeiShu" +msgstr "" + +#: audits/signal_handlers/login_log.py:40 authentication/views/login.py:101 +#: authentication/views/slack.py:87 notifications/backends/__init__.py:16 +#: settings/serializers/auth/slack.py:10 settings/serializers/auth/slack.py:12 +#: users/models/user.py:762 users/models/user.py:934 +msgid "Slack" +msgstr "" + +#: audits/signal_handlers/login_log.py:41 authentication/views/dingtalk.py:161 +#: authentication/views/login.py:83 notifications/backends/__init__.py:12 +#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:759 +#: users/models/user.py:931 +msgid "DingTalk" +msgstr "" + +#: audits/signal_handlers/login_log.py:42 +#: authentication/models/temp_token.py:16 +msgid "Temporary token" +msgstr "" + +#: audits/signal_handlers/login_log.py:43 authentication/views/login.py:107 +#: settings/serializers/auth/passkey.py:8 +#: settings/serializers/auth/passkey.py:11 +msgid "Passkey" +msgstr "" + +#: audits/tasks.py:117 +msgid "Clean audits session task log" +msgstr "" + +#: audits/tasks.py:130 +msgid "Upload FTP file to external storage" +msgstr "" + +#: authentication/api/access_key.py:39 +msgid "Access keys can be created at most 10" +msgstr "" + +#: authentication/api/common.py:34 settings/serializers/auth/sms.py:117 +#, python-format +msgid "The value in the parameter must contain %s" +msgstr "" + +#: authentication/api/confirm.py:50 +msgid "This action require verify your MFA" +msgstr "" + +#: authentication/api/connection_token.py:265 +msgid "Reusable connection token is not allowed, global setting not enabled" +msgstr "" + +#: authentication/api/connection_token.py:379 +msgid "Anonymous account is not supported for this asset" +msgstr "" + +#: authentication/api/connection_token.py:399 +msgid "Account not found" +msgstr "" + +#: authentication/api/connection_token.py:402 +msgid "Permission expired" +msgstr "" + +#: authentication/api/connection_token.py:435 +msgid "ACL action is reject: {}({})" +msgstr "" + +#: authentication/api/connection_token.py:439 +msgid "ACL action is review" +msgstr "" + +#: authentication/api/mfa.py:62 +msgid "Current user not support mfa type: {}" +msgstr "" + +#: authentication/api/password.py:33 terminal/api/session/session.py:325 +#: users/views/profile/reset.py:63 +msgid "User does not exist: {}" +msgstr "" + +#: authentication/api/password.py:33 users/views/profile/reset.py:166 +msgid "No user matched" +msgstr "" + +#: authentication/api/password.py:37 +msgid "" +"The user is from {}, please go to the corresponding system to change the " +"password" +msgstr "" + +#: authentication/api/password.py:65 +#: authentication/templates/authentication/login.html:360 +#: users/templates/users/forgot_password.html:41 +#: users/templates/users/forgot_password.html:42 +#: users/templates/users/forgot_password_previewing.html:13 +#: users/templates/users/forgot_password_previewing.html:14 +msgid "Forgot password" +msgstr "" + +#: authentication/apps.py:7 +msgid "App Authentication" +msgstr "" + +#: authentication/backends/custom.py:59 +#: authentication/backends/oauth2/backends.py:173 +msgid "User invalid, disabled or expired" +msgstr "" + +#: authentication/backends/drf.py:52 +msgid "Invalid token header. No credentials provided." +msgstr "" + +#: authentication/backends/drf.py:55 +msgid "Invalid token header. Sign string should not contain spaces." +msgstr "" + +#: authentication/backends/drf.py:61 +msgid "" +"Invalid token header. Sign string should not contain invalid characters." +msgstr "" + +#: authentication/backends/drf.py:74 +msgid "Invalid token or cache refreshed." +msgstr "" + +#: authentication/backends/passkey/api.py:37 +msgid "Only register passkey for local user" +msgstr "" + +#: authentication/backends/passkey/api.py:65 +msgid "Auth failed" +msgstr "" + +#: authentication/backends/passkey/fido.py:148 +msgid "This key is not registered" +msgstr "" + +#: authentication/backends/passkey/models.py:13 +msgid "Added on" +msgstr "" + +#: authentication/backends/passkey/models.py:14 +#: authentication/models/access_key.py:26 +#: authentication/models/private_token.py:8 +msgid "Date last used" +msgstr "" + +#: authentication/backends/passkey/models.py:15 +msgid "Credential ID" +msgstr "" + +#: authentication/confirm/password.py:16 +msgid "Authentication failed password incorrect" +msgstr "" + +#: authentication/confirm/relogin.py:10 +msgid "Login time has exceeded {} minutes, please login again" +msgstr "" + +#: authentication/errors/const.py:18 +msgid "Username/password check failed" +msgstr "" + +#: authentication/errors/const.py:19 +msgid "Password decrypt failed" +msgstr "" + +#: authentication/errors/const.py:20 +msgid "MFA failed" +msgstr "" + +#: authentication/errors/const.py:21 +msgid "MFA unset" +msgstr "" + +#: authentication/errors/const.py:22 +msgid "Username does not exist" +msgstr "" + +#: authentication/errors/const.py:23 +msgid "Password expired" +msgstr "" + +#: authentication/errors/const.py:24 +msgid "Disabled or expired" +msgstr "" + +#: authentication/errors/const.py:25 +msgid "This account is inactive." +msgstr "" + +#: authentication/errors/const.py:26 +msgid "This account is expired" +msgstr "" + +#: authentication/errors/const.py:27 +msgid "Auth backend not match" +msgstr "" + +#: authentication/errors/const.py:28 +msgid "ACL is not allowed" +msgstr "" + +#: authentication/errors/const.py:29 +msgid "Only local users are allowed" +msgstr "" + +#: authentication/errors/const.py:39 +msgid "No session found, check your cookie" +msgstr "" + +#: authentication/errors/const.py:41 +#, python-brace-format +msgid "" +"The username or password you entered is incorrect, please enter it again. " +"You can also try {times_try} times (The account will be temporarily locked " +"for {block_time} minutes)" +msgstr "" + +#: authentication/errors/const.py:47 authentication/errors/const.py:55 +msgid "" +"The account has been locked (please contact admin to unlock it or try again " +"after {} minutes)" +msgstr "" + +#: authentication/errors/const.py:51 +msgid "" +"The address has been locked (please contact admin to unlock it or try again " +"after {} minutes)" +msgstr "" + +#: authentication/errors/const.py:59 +#, python-brace-format +msgid "" +"{error}, You can also try {times_try} times (The account will be temporarily " +"locked for {block_time} minutes)" +msgstr "" + +#: authentication/errors/const.py:63 +msgid "MFA required" +msgstr "" + +#: authentication/errors/const.py:64 +msgid "MFA not set, please set it first" +msgstr "" + +#: authentication/errors/const.py:65 +msgid "Login confirm required" +msgstr "" + +#: authentication/errors/const.py:66 +msgid "Wait login confirm ticket for accept" +msgstr "" + +#: authentication/errors/const.py:67 +msgid "Login confirm ticket was {}" +msgstr "" + +#: authentication/errors/failed.py:149 +msgid "Current IP and Time period is not allowed" +msgstr "" + +#: authentication/errors/failed.py:154 +msgid "Please enter MFA code" +msgstr "" + +#: authentication/errors/failed.py:159 +msgid "Please enter SMS code" +msgstr "" + +#: authentication/errors/failed.py:164 users/exceptions.py:15 +msgid "Phone not set" +msgstr "" + +#: authentication/errors/mfa.py:8 +msgid "SSO auth closed" +msgstr "" + +#: authentication/errors/mfa.py:18 authentication/views/wecom.py:59 +msgid "WeCom is already bound" +msgstr "" + +#: authentication/errors/mfa.py:23 authentication/views/wecom.py:159 +#: authentication/views/wecom.py:201 +msgid "WeCom is not bound" +msgstr "" + +#: authentication/errors/mfa.py:28 authentication/views/dingtalk.py:213 +#: authentication/views/dingtalk.py:255 +msgid "DingTalk is not bound" +msgstr "" + +#: authentication/errors/mfa.py:33 authentication/views/feishu.py:138 +msgid "FeiShu is not bound" +msgstr "" + +#: authentication/errors/mfa.py:38 authentication/views/lark.py:48 +msgid "Lark is not bound" +msgstr "" + +#: authentication/errors/mfa.py:43 authentication/views/slack.py:127 +msgid "Slack is not bound" +msgstr "" + +#: authentication/errors/mfa.py:48 +msgid "Your password is invalid" +msgstr "" + +#: authentication/errors/mfa.py:53 +#, python-format +msgid "Please wait for %s seconds before retry" +msgstr "" + +#: authentication/errors/redirect.py:85 authentication/mixins.py:323 +msgid "Your password is too simple, please change it for security" +msgstr "" + +#: authentication/errors/redirect.py:93 authentication/mixins.py:330 +msgid "You should to change your password before login" +msgstr "" + +#: authentication/errors/redirect.py:101 authentication/mixins.py:337 +msgid "Your password has expired, please reset before logging in" +msgstr "" + +#: authentication/forms.py:39 +msgid "Auto login" +msgstr "" + +#: authentication/forms.py:52 +msgid "MFA Code" +msgstr "" + +#: authentication/forms.py:53 +msgid "MFA type" +msgstr "" + +#: authentication/forms.py:61 +#: authentication/templates/authentication/_captcha_field.html:15 +msgid "Captcha" +msgstr "" + +#: authentication/forms.py:66 users/forms/profile.py:27 +msgid "MFA code" +msgstr "" + +#: authentication/forms.py:68 +msgid "Dynamic code" +msgstr "" + +#: authentication/mfa/base.py:7 +msgid "Please input security code" +msgstr "" + +#: authentication/mfa/custom.py:20 +msgid "MFA Custom code invalid" +msgstr "" + +#: authentication/mfa/custom.py:26 +msgid "MFA custom verification code" +msgstr "" + +#: authentication/mfa/custom.py:56 +msgid "MFA custom global enabled, cannot disable" +msgstr "" + +#: authentication/mfa/otp.py:7 +msgid "OTP code invalid, or server time error" +msgstr "" + +#: authentication/mfa/otp.py:12 +msgid "OTP" +msgstr "" + +#: authentication/mfa/otp.py:13 +msgid "OTP verification code" +msgstr "" + +#: authentication/mfa/otp.py:48 +msgid "Virtual OTP based MFA" +msgstr "" + +#: authentication/mfa/radius.py:7 +msgid "Radius verify code invalid" +msgstr "" + +#: authentication/mfa/radius.py:13 +msgid "Radius verification code" +msgstr "" + +#: authentication/mfa/radius.py:44 +msgid "Radius global enabled, cannot disable" +msgstr "" + +#: authentication/mfa/sms.py:7 +msgid "SMS verify code invalid" +msgstr "" + +#: authentication/mfa/sms.py:12 authentication/serializers/password_mfa.py:16 +#: authentication/serializers/password_mfa.py:24 +#: settings/serializers/auth/sms.py:17 settings/serializers/auth/sms.py:32 +#: users/forms/profile.py:103 users/forms/profile.py:108 +#: users/templates/users/forgot_password.html:157 +#: users/views/profile/reset.py:100 +msgid "SMS" +msgstr "" + +#: authentication/mfa/sms.py:13 +msgid "SMS verification code" +msgstr "" + +#: authentication/mfa/sms.py:57 +msgid "Set phone number to enable" +msgstr "" + +#: authentication/mfa/sms.py:61 +msgid "Clear phone number to disable" +msgstr "" + +#: authentication/middleware.py:94 settings/utils/ldap.py:679 +msgid "Authentication failed (before login check failed): {}" +msgstr "" + +#: authentication/mixins.py:82 +msgid "User is invalid" +msgstr "" + +#: authentication/mixins.py:97 +msgid "" +"The administrator has enabled 'Only allow login from user source'. \n" +" The current user source is {}. Please contact the administrator." +msgstr "" + +#: authentication/mixins.py:273 +msgid "The MFA type ({}) is not enabled" +msgstr "" + +#: authentication/mixins.py:313 +msgid "Please change your password" +msgstr "" + +#: authentication/models/access_key.py:22 +#: terminal/models/component/endpoint.py:110 +msgid "IP group" +msgstr "" + +#: authentication/models/connection_token.py:38 +#: terminal/serializers/storage.py:114 +msgid "Account name" +msgstr "" + +#: authentication/models/connection_token.py:39 +msgid "Input username" +msgstr "" + +#: authentication/models/connection_token.py:40 +#: authentication/serializers/connection_token.py:18 +msgid "Input secret" +msgstr "" + +#: authentication/models/connection_token.py:41 +#: authentication/serializers/connect_token_secret.py:114 +#: settings/serializers/msg.py:29 terminal/models/applet/applet.py:42 +#: terminal/models/virtualapp/virtualapp.py:24 +#: terminal/serializers/session.py:21 terminal/serializers/session.py:48 +#: terminal/serializers/storage.py:71 +msgid "Protocol" +msgstr "" + +#: authentication/models/connection_token.py:42 +msgid "Connect method" +msgstr "" + +#: authentication/models/connection_token.py:43 +msgid "Connect options" +msgstr "" + +#: authentication/models/connection_token.py:44 +msgid "User display" +msgstr "" + +#: authentication/models/connection_token.py:45 +msgid "Asset display" +msgstr "" + +#: authentication/models/connection_token.py:46 +msgid "Reusable" +msgstr "" + +#: authentication/models/connection_token.py:51 +#: perms/models/asset_permission.py:83 +msgid "From ticket" +msgstr "" + +#: authentication/models/connection_token.py:58 +msgid "Can expire connection token" +msgstr "" + +#: authentication/models/connection_token.py:59 +msgid "Can reuse connection token" +msgstr "" + +#: authentication/models/connection_token.py:61 +msgid "Connection token" +msgstr "" + +#: authentication/models/connection_token.py:118 +msgid "Connection token inactive" +msgstr "" + +#: authentication/models/connection_token.py:122 +msgid "Connection token expired at: {}" +msgstr "" + +#: authentication/models/connection_token.py:125 +msgid "No user or invalid user" +msgstr "" + +#: authentication/models/connection_token.py:128 +msgid "No asset or inactive asset" +msgstr "" + +#: authentication/models/connection_token.py:274 +msgid "Can view super connection token secret" +msgstr "" + +#: authentication/models/connection_token.py:276 +msgid "Super connection token" +msgstr "" + +#: authentication/models/private_token.py:11 +msgid "Private Token" +msgstr "" + +#: authentication/models/sso_token.py:15 +msgid "Expired" +msgstr "" + +#: authentication/models/sso_token.py:20 +msgid "SSO token" +msgstr "" + +#: authentication/models/temp_token.py:11 +msgid "Verified" +msgstr "" + +#: authentication/notifications.py:19 +msgid "Different city login reminder" +msgstr "" + +#: authentication/notifications.py:52 +msgid "binding reminder" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:116 +msgid "Is builtin" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:120 +msgid "Options" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:127 +#: ops/notifications.py:18 +msgid "Component" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:138 +msgid "Expired now" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:170 +#: terminal/models/virtualapp/virtualapp.py:25 +msgid "Image name" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:171 +#: terminal/models/virtualapp/virtualapp.py:27 +msgid "Image port" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:172 +#: terminal/models/virtualapp/virtualapp.py:26 +msgid "Image protocol" +msgstr "" + +#: authentication/serializers/connection_token.py:16 +msgid "Expired time" +msgstr "" + +#: authentication/serializers/connection_token.py:20 +msgid "Ticket info" +msgstr "" + +#: authentication/serializers/connection_token.py:21 +#: perms/models/asset_permission.py:77 perms/serializers/permission.py:42 +#: perms/serializers/permission.py:64 +#: tickets/models/ticket/apply_application.py:28 +#: tickets/models/ticket/apply_asset.py:18 +msgid "Actions" +msgstr "" + +#: authentication/serializers/connection_token.py:42 +#: perms/serializers/permission.py:44 perms/serializers/permission.py:65 +#: users/serializers/user.py:101 users/serializers/user.py:184 +msgid "Is expired" +msgstr "" + +#: authentication/serializers/password_mfa.py:29 +#: users/templates/users/forgot_password.html:153 +msgid "The {} cannot be empty" +msgstr "" + +#: authentication/serializers/token.py:22 +msgid "Access IP" +msgstr "" + +#: authentication/serializers/token.py:92 perms/serializers/permission.py:43 +#: perms/serializers/permission.py:66 users/serializers/user.py:102 +#: users/serializers/user.py:181 +msgid "Is valid" +msgstr "" + +#: authentication/tasks.py:11 +msgid "Clean expired session" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:6 +msgid "API key list" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:18 +msgid "Using api key sign api header, every requests header difference" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:19 +msgid "docs" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:48 +msgid "Show" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:66 +#: users/const.py:42 users/models/user.py:654 users/serializers/profile.py:92 +#: users/templates/users/user_verify_mfa.html:36 +msgid "Disable" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:67 +#: users/const.py:43 users/models/user.py:655 users/serializers/profile.py:93 +#: users/templates/users/mfa_setting.html:26 +#: users/templates/users/mfa_setting.html:68 +msgid "Enable" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:147 +msgid "Delete success" +msgstr "" + +#: authentication/templates/authentication/_captcha_field.html:8 +msgid "Play CAPTCHA as audio file" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:5 +msgid "MFA confirm" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:17 +msgid "Need MFA for view auth" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:20 +#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:37 +#: templates/_modal.html:23 templates/flash_message_standalone.html:37 +#: users/templates/users/user_password_verify.html:20 +msgid "Confirm" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:25 +msgid "Code error" +msgstr "" + +#: authentication/templates/authentication/_msg_different_city.html:3 +#: authentication/templates/authentication/_msg_oauth_bind.html:3 +#: authentication/templates/authentication/_msg_reset_password.html:3 +#: 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:465 +#: 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:32 +#: users/templates/users/_msg_account_expire_reminder.html:4 +#: users/templates/users/_msg_password_expire_reminder.html:4 +#: users/templates/users/_msg_reset_mfa.html:4 +#: users/templates/users/_msg_reset_ssh_key.html:4 +msgid "Hello" +msgstr "" + +#: authentication/templates/authentication/_msg_different_city.html:6 +msgid "Your account has remote login behavior, please pay attention" +msgstr "" + +#: authentication/templates/authentication/_msg_different_city.html:16 +msgid "" +"If you suspect that the login behavior is abnormal, please modify the " +"account password in time." +msgstr "" + +#: authentication/templates/authentication/_msg_oauth_bind.html:6 +msgid "Your account has just been bound to" +msgstr "" + +#: authentication/templates/authentication/_msg_oauth_bind.html:17 +msgid "If the operation is not your own, unbind and change the password." +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:6 +msgid "" +"Please click the link below to reset your password, if not your request, " +"concern your account security" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:10 +msgid "Click here reset password" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:16 +#: users/templates/users/_msg_user_created.html:22 +msgid "This link is valid for 1 hour. After it expires" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:17 +#: users/templates/users/_msg_user_created.html:23 +msgid "request new one" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password_code.html:12 +#: terminal/models/session/sharing.py:27 terminal/models/session/sharing.py:97 +#: terminal/templates/terminal/_msg_session_sharing.html:12 +#: users/forms/profile.py:106 users/templates/users/forgot_password.html:98 +msgid "Verify code" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password_code.html:15 +msgid "" +"Copy the verification code to the Reset Password page to reset the password." +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password_code.html:18 +msgid "The validity period of the verification code is one minute" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:5 +msgid "Your password has just been successfully updated" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:9 +#: authentication/templates/authentication/_msg_rest_public_key_success.html:9 +msgid "Browser" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:13 +msgid "" +"If the password update was not initiated by you, your account may have " +"security issues" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:14 +#: authentication/templates/authentication/_msg_rest_public_key_success.html:14 +msgid "If you have any questions, you can contact the administrator" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_public_key_success.html:5 +msgid "Your public key has just been successfully updated" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_public_key_success.html:13 +msgid "" +"If the public key update was not initiated by you, your account may have " +"security issues" +msgstr "" + +#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:28 +#: templates/flash_message_standalone.html:28 tickets/const.py:18 +msgid "Cancel" +msgstr "" + +#: authentication/templates/authentication/login.html:276 +msgid "" +"Configuration file has problems and cannot be logged in. Please contact the " +"administrator or view latest docs" +msgstr "" + +#: authentication/templates/authentication/login.html:277 +msgid "If you are administrator, you can update the config resolve it, set" +msgstr "" + +#: authentication/templates/authentication/login.html:375 +msgid "More login options" +msgstr "" + +#: authentication/templates/authentication/login_mfa.html:6 +msgid "MFA Auth" +msgstr "" + +#: authentication/templates/authentication/login_mfa.html:19 +#: users/templates/users/user_otp_check_password.html:12 +#: users/templates/users/user_otp_enable_bind.html:24 +#: users/templates/users/user_otp_enable_install_app.html:31 +#: users/templates/users/user_verify_mfa.html:30 +msgid "Next" +msgstr "" + +#: authentication/templates/authentication/login_mfa.html:22 +msgid "Can't provide security? Please contact the administrator!" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:41 +msgid "Refresh" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:46 +msgid "Copy link" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:51 +msgid "Return" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:117 +msgid "Copy success" +msgstr "" + +#: authentication/templates/authentication/passkey.html:162 +msgid "" +"This page is not served over HTTPS. Please use HTTPS to ensure security of " +"your credentials." +msgstr "" + +#: authentication/templates/authentication/passkey.html:173 +msgid "Do you want to retry ?" +msgstr "" + +#: authentication/utils.py:24 common/utils/ip/geoip/utils.py:24 +#: xpack/plugins/cloud/const.py:32 +msgid "LAN" +msgstr "" + +#: authentication/views/base.py:73 +#: perms/templates/perms/_msg_permed_items_expire.html:21 +msgid "If you have any question, please contact the administrator" +msgstr "" + +#: authentication/views/base.py:146 +#, python-format +msgid "%s query user failed" +msgstr "" + +#: authentication/views/base.py:155 +#, python-format +msgid "The %s is already bound to another user" +msgstr "" + +#: authentication/views/base.py:162 +#, python-format +msgid "Binding %s successfully" +msgstr "" + +#: authentication/views/dingtalk.py:42 +msgid "DingTalk Error, Please contact your system administrator" +msgstr "" + +#: authentication/views/dingtalk.py:45 authentication/views/dingtalk.py:212 +msgid "DingTalk Error" +msgstr "" + +#: authentication/views/dingtalk.py:57 authentication/views/feishu.py:68 +#: authentication/views/slack.py:47 authentication/views/wecom.py:55 +msgid "" +"The system configuration is incorrect. Please contact your administrator" +msgstr "" + +#: authentication/views/dingtalk.py:61 +msgid "DingTalk is already bound" +msgstr "" + +#: authentication/views/dingtalk.py:130 +msgid "Invalid user_id" +msgstr "" + +#: authentication/views/dingtalk.py:146 +msgid "DingTalk query user failed" +msgstr "" + +#: authentication/views/dingtalk.py:155 +msgid "The DingTalk is already bound to another user" +msgstr "" + +#: authentication/views/dingtalk.py:162 +msgid "Binding DingTalk successfully" +msgstr "" + +#: authentication/views/dingtalk.py:214 authentication/views/dingtalk.py:249 +msgid "Failed to get user from DingTalk" +msgstr "" + +#: authentication/views/dingtalk.py:256 +msgid "Please login with a password and then bind the DingTalk" +msgstr "" + +#: authentication/views/feishu.py:43 authentication/views/feishu.py:137 +msgid "FeiShu Error" +msgstr "" + +#: authentication/views/feishu.py:44 +msgid "FeiShu is already bound" +msgstr "" + +#: authentication/views/feishu.py:139 +msgid "Failed to get user from FeiShu" +msgstr "" + +#: authentication/views/lark.py:19 authentication/views/lark.py:47 +msgid "Lark Error" +msgstr "" + +#: authentication/views/lark.py:20 +msgid "Lark is already bound" +msgstr "" + +#: authentication/views/lark.py:49 +msgid "Failed to get user from Lark" +msgstr "" + +#: authentication/views/login.py:230 +msgid "Redirecting" +msgstr "" + +#: authentication/views/login.py:231 +msgid "Redirecting to {} authentication" +msgstr "" + +#: authentication/views/login.py:254 +msgid "Login timeout, please try again." +msgstr "" + +#: authentication/views/login.py:297 +msgid "User email already exists ({})" +msgstr "" + +#: authentication/views/login.py:375 +msgid "" +"Wait for {} confirm, You also can copy link to her/him
\n" +" Don't close this page" +msgstr "" + +#: authentication/views/login.py:380 +msgid "No ticket found" +msgstr "" + +#: authentication/views/login.py:416 +msgid "Logout success" +msgstr "" + +#: authentication/views/login.py:417 +msgid "Logout success, return login page" +msgstr "" + +#: authentication/views/slack.py:35 authentication/views/slack.py:126 +msgid "Slack Error" +msgstr "" + +#: authentication/views/slack.py:63 +msgid "Slack is already bound" +msgstr "" + +#: authentication/views/slack.py:128 +msgid "Failed to get user from Slack" +msgstr "" + +#: authentication/views/wecom.py:40 +msgid "WeCom Error, Please contact your system administrator" +msgstr "" + +#: authentication/views/wecom.py:43 authentication/views/wecom.py:158 +msgid "WeCom Error" +msgstr "" + +#: authentication/views/wecom.py:118 +msgid "Wecom" +msgstr "" + +#: authentication/views/wecom.py:160 authentication/views/wecom.py:195 +msgid "Failed to get user from WeCom" +msgstr "" + +#: authentication/views/wecom.py:202 +msgid "Please login with a password and then bind the WeCom" +msgstr "" + +#: common/api/action.py:51 +msgid "Request file format may be wrong" +msgstr "" + +#: common/const/choices.py:10 +msgid "Manual trigger" +msgstr "" + +#: common/const/choices.py:11 +msgid "Timing trigger" +msgstr "" + +#: common/const/choices.py:15 +msgid "Ready" +msgstr "" + +#: common/const/choices.py:17 ops/const.py:73 +msgid "Running" +msgstr "" + +#: common/const/choices.py:21 +msgid "Canceled" +msgstr "" + +#: common/const/common.py:5 +#, python-format +msgid "%(name)s was created successfully" +msgstr "" + +#: common/const/common.py:6 +#, python-format +msgid "%(name)s was updated successfully" +msgstr "" + +#: common/db/encoder.py:11 +msgid "gettext_lazy" +msgstr "" + +#: common/db/fields.py:106 +msgid "Marshal dict data to char field" +msgstr "" + +#: common/db/fields.py:110 +msgid "Marshal dict data to text field" +msgstr "" + +#: common/db/fields.py:122 +msgid "Marshal list data to char field" +msgstr "" + +#: common/db/fields.py:126 +msgid "Marshal list data to text field" +msgstr "" + +#: common/db/fields.py:130 +msgid "Marshal data to char field" +msgstr "" + +#: common/db/fields.py:134 +msgid "Marshal data to text field" +msgstr "" + +#: common/db/fields.py:167 +msgid "Encrypt field using Secret Key" +msgstr "" + +#: common/db/fields.py:582 +msgid "" +"Invalid JSON data for JSONManyToManyField, should be like {'type': 'all'} or " +"{'type': 'ids', 'ids': []} or {'type': 'attrs', 'attrs': [{'name': 'ip', " +"'match': 'exact', 'value': '1.1.1.1'}}" +msgstr "" + +#: common/db/fields.py:589 +msgid "Invalid type, should be \"all\", \"ids\" or \"attrs\"" +msgstr "" + +#: common/db/fields.py:592 +msgid "Invalid ids for ids, should be a list" +msgstr "" + +#: common/db/fields.py:594 common/db/fields.py:599 +#: common/serializers/fields.py:133 tickets/serializers/ticket/common.py:58 +#: xpack/plugins/cloud/serializers/account_attrs.py:56 +#: xpack/plugins/cloud/serializers/account_attrs.py:79 +#: xpack/plugins/cloud/serializers/account_attrs.py:150 +msgid "This field is required." +msgstr "" + +#: common/db/fields.py:597 common/db/fields.py:602 +msgid "Invalid attrs, should be a list of dict" +msgstr "" + +#: common/db/fields.py:604 +msgid "Invalid attrs, should be has name and value" +msgstr "" + +#: common/db/mixins.py:32 +msgid "is discard" +msgstr "" + +#: common/db/mixins.py:33 +msgid "discard time" +msgstr "" + +#: common/db/models.py:33 users/models/user.py:918 +msgid "Updated by" +msgstr "" + +#: common/db/validators.py:9 +msgid "Invalid port range, should be like and within {}-{}" +msgstr "" + +#: common/drf/exc_handlers.py:26 +msgid "Object" +msgstr "" + +#: common/drf/metadata.py:127 +msgid "Org ID" +msgstr "" + +#: common/drf/parsers/base.py:21 +msgid "The file content overflowed (The maximum length `{}` bytes)" +msgstr "" + +#: common/drf/parsers/base.py:199 +msgid "Parse file error: {}" +msgstr "" + +#: common/drf/parsers/excel.py:14 +msgid "Invalid excel file" +msgstr "" + +#: common/drf/renders/base.py:208 +msgid "" +"{} - The encryption password has not been set - please go to personal " +"information -> file encryption password to set the encryption password" +msgstr "" + +#: common/exceptions.py:15 +#, python-format +msgid "%s object does not exist." +msgstr "" + +#: common/exceptions.py:25 +msgid "Someone else is doing this. Please wait for complete" +msgstr "" + +#: common/exceptions.py:30 +msgid "Your request timeout" +msgstr "" + +#: common/exceptions.py:35 +msgid "M2M reverse not allowed" +msgstr "" + +#: common/exceptions.py:41 +msgid "Is referenced by other objects and cannot be deleted" +msgstr "" + +#: common/exceptions.py:51 +msgid "This action require confirm current user" +msgstr "" + +#: common/exceptions.py:59 +msgid "Unexpect error occur" +msgstr "" + +#: common/plugins/es.py:31 +msgid "Invalid elasticsearch config" +msgstr "" + +#: common/plugins/es.py:36 +msgid "Not Support Elasticsearch8" +msgstr "" + +#: common/sdk/im/exceptions.py:23 +msgid "Network error, please contact system administrator" +msgstr "" + +#: common/sdk/im/slack/__init__.py:77 +msgid "Unknown error occur" +msgstr "" + +#: common/sdk/im/wecom/__init__.py:16 +msgid "WeCom error, please contact system administrator" +msgstr "" + +#: common/sdk/sms/alibaba.py:56 +msgid "Signature does not match" +msgstr "" + +#: common/sdk/sms/cmpp2.py:44 +msgid "sp_id is 6 bits" +msgstr "" + +#: common/sdk/sms/cmpp2.py:214 +msgid "Failed to connect to the CMPP gateway server, err: {}" +msgstr "" + +#: common/sdk/sms/custom_file.py:41 +msgid "The custom sms file is invalid" +msgstr "" + +#: common/sdk/sms/custom_file.py:47 +#, python-format +msgid "SMS sending failed[%s]: %s" +msgstr "" + +#: common/sdk/sms/endpoint.py:16 +msgid "Alibaba cloud" +msgstr "" + +#: common/sdk/sms/endpoint.py:17 +msgid "Tencent cloud" +msgstr "" + +#: common/sdk/sms/endpoint.py:18 xpack/plugins/cloud/const.py:13 +msgid "Huawei Cloud" +msgstr "" + +#: common/sdk/sms/endpoint.py:19 +msgid "CMPP v2.0" +msgstr "" + +#: common/sdk/sms/endpoint.py:21 +msgid "Custom type (File)" +msgstr "" + +#: common/sdk/sms/endpoint.py:32 +msgid "SMS provider not support: {}" +msgstr "" + +#: common/sdk/sms/endpoint.py:54 +msgid "SMS verification code signature or template invalid" +msgstr "" + +#: common/sdk/sms/exceptions.py:8 +msgid "The verification code has expired. Please resend it" +msgstr "" + +#: common/sdk/sms/exceptions.py:13 +msgid "The verification code is incorrect" +msgstr "" + +#: common/sdk/sms/exceptions.py:18 +msgid "Please wait {} seconds before sending" +msgstr "" + +#: common/serializers/common.py:90 +msgid "Children" +msgstr "" + +#: common/serializers/fields.py:134 +#, python-brace-format +msgid "Invalid pk \"{pk_value}\" - object does not exist." +msgstr "" + +#: common/serializers/fields.py:135 +#, python-brace-format +msgid "Incorrect type. Expected pk value, received {data_type}." +msgstr "" + +#: common/serializers/fields.py:209 +msgid "Invalid data type, should be list" +msgstr "" + +#: common/serializers/fields.py:224 +msgid "Invalid choice: {}" +msgstr "" + +#: common/serializers/mixin.py:409 +msgid "Labels" +msgstr "" + +#: common/tasks.py:31 common/utils/verify_code.py:16 +msgid "Send email" +msgstr "" + +#: common/tasks.py:58 +msgid "Send email attachment" +msgstr "" + +#: common/tasks.py:80 terminal/tasks.py:58 +msgid "Upload session replay to external storage" +msgstr "" + +#: common/utils/ip/geoip/utils.py:26 +msgid "Invalid ip" +msgstr "" + +#: common/utils/ip/utils.py:98 +msgid "Invalid address" +msgstr "" + +#: common/utils/translate.py:45 +#, python-format +msgid "Hello %s" +msgstr "" + +#: common/validators.py:16 +msgid "Special char not allowed" +msgstr "" + +#: common/validators.py:42 +msgid "Should not contains special characters" +msgstr "" + +#: common/validators.py:47 +msgid "The mobile phone number format is incorrect" +msgstr "" + +#: jumpserver/conf.py:459 +#, python-brace-format +msgid "The verification code is: {code}" +msgstr "" + +#: jumpserver/conf.py:464 +msgid "Create account successfully" +msgstr "" + +#: jumpserver/conf.py:466 +msgid "Your account has been created successfully" +msgstr "" + +#: jumpserver/context_processor.py:14 +msgid "JumpServer Open Source Bastion Host" +msgstr "" + +#: jumpserver/views/celery_flower.py:22 +msgid "

Flower service unavailable, check it

" +msgstr "" + +#: jumpserver/views/other.py:27 +msgid "" +"
Luna is a separately deployed program, you need to deploy Luna, koko, " +"configure nginx for url distribution,
If you see this page, " +"prove that you are not accessing the nginx listening port. Good luck." +msgstr "" + +#: jumpserver/views/other.py:72 +msgid "Websocket server run on port: {}, you should proxy it on nginx" +msgstr "" + +#: jumpserver/views/other.py:86 +msgid "" +"
Koko is a separately deployed program, you need to deploy Koko, " +"configure nginx for url distribution,
If you see this page, " +"prove that you are not accessing the nginx listening port. Good luck." +msgstr "" + +#: labels/apps.py:8 +msgid "App Labels" +msgstr "" + +#: labels/models.py:36 +msgid "Resource ID" +msgstr "" + +#: labels/models.py:41 +msgid "Labeled resource" +msgstr "" + +#: labels/serializers.py:22 +msgid "Resource count" +msgstr "" + +#: labels/serializers.py:28 +msgid "Cannot contain \":,\"" +msgstr "" + +#: labels/serializers.py:43 +msgid "Resource type" +msgstr "" + +#: notifications/apps.py:7 +msgid "App Notifications" +msgstr "" + +#: notifications/backends/__init__.py:13 +msgid "Site message" +msgstr "" + +#: notifications/models/notification.py:14 +msgid "receive backend" +msgstr "" + +#: notifications/models/notification.py:18 +msgid "User message" +msgstr "" + +#: notifications/models/notification.py:21 +msgid "{} subscription" +msgstr "" + +#: notifications/models/notification.py:34 +msgid "System message" +msgstr "" + +#: notifications/notifications.py:46 +msgid "Publish the station message" +msgstr "" + +#: ops/ansible/inventory.py:107 ops/models/job.py:65 +msgid "No account available" +msgstr "" + +#: ops/ansible/inventory.py:286 +msgid "Ansible disabled" +msgstr "" + +#: ops/ansible/inventory.py:302 +msgid "Skip hosts below:" +msgstr "" + +#: ops/api/celery.py:66 ops/api/celery.py:81 +msgid "Waiting task start" +msgstr "" + +#: ops/api/celery.py:262 +msgid "Task {} not found" +msgstr "" + +#: ops/api/celery.py:267 +msgid "Task {} args or kwargs error" +msgstr "" + +#: ops/api/job.py:81 +#, python-brace-format +msgid "" +"Asset ({asset}) must have at least one of the following protocols added: " +"SSH, SFTP, or WinRM" +msgstr "" + +#: ops/api/job.py:82 +#, python-brace-format +msgid "Asset ({asset}) authorization is missing SSH, SFTP, or WinRM protocol" +msgstr "" + +#: ops/api/job.py:83 +#, python-brace-format +msgid "Asset ({asset}) authorization lacks upload permissions" +msgstr "" + +#: ops/api/job.py:168 +msgid "Duplicate file exists" +msgstr "" + +#: ops/api/job.py:173 +#, python-brace-format +msgid "" +"File size exceeds maximum limit. Please select a file smaller than {limit}MB" +msgstr "" + +#: ops/api/job.py:237 +msgid "" +"The task is being created and cannot be interrupted. Please try again later." +msgstr "" + +#: ops/api/playbook.py:39 +msgid "Currently playbook is being used in a job" +msgstr "" + +#: ops/api/playbook.py:96 +msgid "Unsupported file content" +msgstr "" + +#: ops/api/playbook.py:98 ops/api/playbook.py:144 ops/api/playbook.py:192 +msgid "Invalid file path" +msgstr "" + +#: ops/api/playbook.py:170 +msgid "This file can not be rename" +msgstr "" + +#: ops/api/playbook.py:189 +msgid "File already exists" +msgstr "" + +#: ops/api/playbook.py:207 +msgid "File key is required" +msgstr "" + +#: ops/api/playbook.py:210 +msgid "This file can not be delete" +msgstr "" + +#: ops/apps.py:9 +msgid "App Ops" +msgstr "" + +#: ops/const.py:6 +msgid "Push" +msgstr "" + +#: ops/const.py:7 +msgid "Verify" +msgstr "" + +#: ops/const.py:8 +msgid "Collect" +msgstr "" + +#: ops/const.py:19 +msgid "Custom password" +msgstr "" + +#: ops/const.py:20 +msgid "All assets use the same random password" +msgstr "" + +#: ops/const.py:21 +msgid "All assets use different random password" +msgstr "" + +#: ops/const.py:33 +msgid "Blank" +msgstr "" + +#: ops/const.py:34 +msgid "VCS" +msgstr "" + +#: ops/const.py:38 ops/models/adhoc.py:44 +msgid "Adhoc" +msgstr "" + +#: ops/const.py:39 ops/models/job.py:149 +msgid "Playbook" +msgstr "" + +#: ops/const.py:40 +msgid "Upload File" +msgstr "" + +#: ops/const.py:44 +msgid "Privileged Only" +msgstr "" + +#: ops/const.py:45 +msgid "Privileged First" +msgstr "" + +#: ops/const.py:50 ops/const.py:61 +msgid "Shell" +msgstr "" + +#: ops/const.py:51 ops/const.py:62 +msgid "Powershell" +msgstr "" + +#: ops/const.py:52 ops/const.py:63 +msgid "Python" +msgstr "" + +#: ops/const.py:53 ops/const.py:64 +msgid "MySQL" +msgstr "" + +#: ops/const.py:54 ops/const.py:66 +msgid "PostgreSQL" +msgstr "" + +#: ops/const.py:55 ops/const.py:67 +msgid "SQLServer" +msgstr "" + +#: ops/const.py:56 ops/const.py:69 +msgid "Raw" +msgstr "" + +#: ops/const.py:57 +msgid "HUAWEI" +msgstr "" + +#: ops/const.py:65 +msgid "MariaDB" +msgstr "" + +#: ops/const.py:68 +msgid "Oracle" +msgstr "" + +#: ops/const.py:75 +msgid "Timeout" +msgstr "" + +#: ops/exception.py:6 +msgid "no valid program entry found." +msgstr "" + +#: ops/mixin.py:23 ops/mixin.py:102 settings/serializers/auth/ldap.py:66 +msgid "Periodic run" +msgstr "" + +#: ops/mixin.py:25 ops/mixin.py:88 ops/mixin.py:108 +#: settings/serializers/auth/ldap.py:73 +msgid "Interval" +msgstr "" + +#: ops/mixin.py:28 ops/mixin.py:86 ops/mixin.py:105 +#: settings/serializers/auth/ldap.py:70 +msgid "Crontab" +msgstr "" + +#: ops/mixin.py:110 +msgid "Run period" +msgstr "" + +#: ops/mixin.py:119 +msgid "* Please enter a valid crontab expression" +msgstr "" + +#: ops/mixin.py:126 +msgid "Range {} to {}" +msgstr "" + +#: ops/mixin.py:137 +msgid "Require interval or crontab setting" +msgstr "" + +#: ops/models/adhoc.py:21 +msgid "Pattern" +msgstr "" + +#: ops/models/adhoc.py:23 ops/models/job.py:146 +msgid "Module" +msgstr "" + +#: ops/models/adhoc.py:24 ops/models/celery.py:81 ops/models/job.py:144 +#: terminal/models/component/task.py:14 +msgid "Args" +msgstr "" + +#: ops/models/base.py:19 +msgid "Account policy" +msgstr "" + +#: ops/models/base.py:20 +msgid "Last execution" +msgstr "" + +#: ops/models/base.py:22 ops/serializers/job.py:17 +msgid "Date last run" +msgstr "" + +#: ops/models/base.py:51 ops/models/job.py:237 +#: xpack/plugins/cloud/models.py:202 +msgid "Result" +msgstr "" + +#: ops/models/base.py:52 ops/models/job.py:238 +msgid "Summary" +msgstr "" + +#: ops/models/celery.py:16 +msgid "Date last publish" +msgstr "" + +#: ops/models/celery.py:70 +msgid "Celery Task" +msgstr "" + +#: ops/models/celery.py:73 +msgid "Can view task monitor" +msgstr "" + +#: ops/models/celery.py:82 terminal/models/component/task.py:15 +msgid "Kwargs" +msgstr "" + +#: ops/models/celery.py:84 terminal/models/session/sharing.py:128 +#: tickets/const.py:25 +msgid "Finished" +msgstr "" + +#: ops/models/celery.py:87 +msgid "Date published" +msgstr "" + +#: ops/models/celery.py:112 +msgid "Celery Task Execution" +msgstr "" + +#: ops/models/job.py:147 +msgid "Chdir" +msgstr "" + +#: ops/models/job.py:148 +msgid "Timeout (Seconds)" +msgstr "" + +#: ops/models/job.py:153 +msgid "Use Parameter Define" +msgstr "" + +#: ops/models/job.py:154 +msgid "Parameters define" +msgstr "" + +#: ops/models/job.py:155 +msgid "Runas" +msgstr "" + +#: ops/models/job.py:157 +msgid "Runas policy" +msgstr "" + +#: ops/models/job.py:221 terminal/notifications.py:174 +msgid "Job" +msgstr "" + +#: ops/models/job.py:244 +msgid "Material" +msgstr "" + +#: ops/models/job.py:246 +msgid "Material Type" +msgstr "" + +#: ops/models/job.py:544 +msgid "Job Execution" +msgstr "" + +#: ops/models/playbook.py:33 +msgid "CreateMethod" +msgstr "" + +#: ops/models/playbook.py:34 +msgid "VCS URL" +msgstr "" + +#: ops/notifications.py:19 +msgid "Server performance" +msgstr "" + +#: ops/notifications.py:25 +msgid "Terminal health check warning" +msgstr "" + +#: ops/notifications.py:70 +#, python-brace-format +msgid "The terminal is offline: {name}" +msgstr "" + +#: ops/notifications.py:75 +#, python-brace-format +msgid "Disk used more than {max_threshold}%: => {value}" +msgstr "" + +#: ops/notifications.py:80 +#, python-brace-format +msgid "Memory used more than {max_threshold}%: => {value}" +msgstr "" + +#: ops/notifications.py:85 +#, python-brace-format +msgid "CPU load more than {max_threshold}: => {value}" +msgstr "" + +#: ops/serializers/celery.py:33 +msgid "Execution cycle" +msgstr "" + +#: ops/serializers/celery.py:35 +msgid "Next execution time" +msgstr "" + +#: ops/serializers/job.py:15 +msgid "Execute after saving" +msgstr "" + +#: ops/serializers/job.py:52 +msgid "Average time cost" +msgstr "" + +#: ops/serializers/job.py:72 +msgid "Job type" +msgstr "" + +#: ops/serializers/job.py:75 terminal/serializers/session.py:56 +msgid "Is finished" +msgstr "" + +#: ops/serializers/job.py:76 +#: settings/templates/ldap/_msg_import_ldap_user.html:7 +msgid "Time cost" +msgstr "" + +#: ops/serializers/job.py:90 +msgid "You do not have permission for the current job." +msgstr "" + +#: ops/tasks.py:38 +msgid "Run ansible task" +msgstr "" + +#: ops/tasks.py:72 +msgid "Run ansible task execution" +msgstr "" + +#: ops/tasks.py:94 +msgid "Clear celery periodic tasks" +msgstr "" + +#: ops/tasks.py:115 +msgid "Create or update periodic tasks" +msgstr "" + +#: ops/tasks.py:123 +msgid "Periodic check service performance" +msgstr "" + +#: ops/tasks.py:129 +msgid "Clean up unexpected jobs" +msgstr "" + +#: ops/tasks.py:136 +msgid "Clean job_execution db record" +msgstr "" + +#: ops/templates/ops/celery_task_log.html:4 +msgid "Task log" +msgstr "" + +#: ops/variables.py:24 +msgid "The current user`s username of JumpServer" +msgstr "" + +#: ops/variables.py:25 +msgid "The id of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:26 +msgid "The type of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:27 +msgid "The category of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:28 +msgid "The name of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:29 +msgid "Address used to connect this asset in JumpServer" +msgstr "" + +#: ops/variables.py:30 +msgid "Port used to connect this asset in JumpServer" +msgstr "" + +#: ops/variables.py:31 +msgid "ID of the job" +msgstr "" + +#: ops/variables.py:32 +msgid "Name of the job" +msgstr "" + +#: orgs/api.py:61 +msgid "The current organization ({}) cannot be deleted" +msgstr "" + +#: orgs/api.py:66 +msgid "" +"LDAP synchronization is set to the current organization. Please switch to " +"another organization before deleting" +msgstr "" + +#: orgs/api.py:76 +msgid "The organization have resource ({}) cannot be deleted" +msgstr "" + +#: orgs/apps.py:7 +msgid "App Organizations" +msgstr "" + +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:91 +#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/serializers/rolebinding.py:44 settings/serializers/auth/ldap.py:63 +#: terminal/templates/terminal/_msg_command_warning.html:21 +#: terminal/templates/terminal/_msg_session_sharing.html:14 +#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:60 +msgid "Organization" +msgstr "" + +#: orgs/mixins/serializers.py:26 rbac/serializers/rolebinding.py:27 +msgid "Org name" +msgstr "" + +#: orgs/models.py:14 +msgid "GLOBAL" +msgstr "" + +#: orgs/models.py:16 +msgid "DEFAULT" +msgstr "" + +#: orgs/models.py:18 +msgid "SYSTEM" +msgstr "" + +#: orgs/models.py:83 rbac/models/role.py:36 settings/models.py:185 +#: terminal/models/applet/applet.py:41 +msgid "Builtin" +msgstr "" + +#: orgs/models.py:93 +msgid "Can view root org" +msgstr "" + +#: orgs/models.py:94 +msgid "Can view all joined org" +msgstr "" + +#: orgs/models.py:236 +msgid "Can not delete virtual org" +msgstr "" + +#: orgs/serializers.py:10 perms/serializers/permission.py:38 +#: rbac/serializers/role.py:27 users/serializers/group.py:54 +msgid "Users amount" +msgstr "" + +#: orgs/serializers.py:11 +msgid "User groups amount" +msgstr "" + +#: orgs/serializers.py:14 perms/serializers/permission.py:41 +msgid "Nodes amount" +msgstr "" + +#: orgs/serializers.py:15 +msgid "Domains amount" +msgstr "" + +#: orgs/serializers.py:16 +msgid "Gateways amount" +msgstr "" + +#: orgs/serializers.py:18 +msgid "Asset permissions amount" +msgstr "" + +#: orgs/tasks.py:9 +msgid "Refresh organization cache" +msgstr "" + +#: perms/apps.py:9 +msgid "App Permissions" +msgstr "" + +#: perms/const.py:12 +msgid "Connect (All protocols)" +msgstr "" + +#: perms/const.py:13 +msgid "Upload (RDP, SFTP)" +msgstr "" + +#: perms/const.py:14 +msgid "Download (RDP, SFTP)" +msgstr "" + +#: perms/const.py:15 +msgid "Copy (RDP, VNC)" +msgstr "" + +#: perms/const.py:16 +msgid "Paste (RDP, VNC)" +msgstr "" + +#: perms/const.py:17 +msgid "Delete (SFTP)" +msgstr "" + +#: perms/const.py:18 +msgid "Share (SSH)" +msgstr "" + +#: perms/const.py:28 +msgid "Transfer" +msgstr "" + +#: perms/const.py:29 +msgid "Clipboard" +msgstr "" + +#: perms/models/asset_permission.py:89 +msgid "Asset permission" +msgstr "" + +#: perms/models/perm_node.py:68 +msgid "Ungrouped" +msgstr "" + +#: perms/models/perm_node.py:70 +msgid "Favorite" +msgstr "" + +#: perms/models/perm_node.py:121 +msgid "Permed asset" +msgstr "" + +#: perms/models/perm_node.py:123 +msgid "Can view my assets" +msgstr "" + +#: perms/models/perm_node.py:124 +msgid "Can view user assets" +msgstr "" + +#: perms/models/perm_node.py:125 +msgid "Can view usergroup assets" +msgstr "" + +#: perms/models/perm_node.py:136 +msgid "Permed account" +msgstr "" + +#: perms/notifications.py:12 perms/notifications.py:44 +msgid "today" +msgstr "" + +#: perms/notifications.py:12 perms/notifications.py:44 +#: settings/serializers/feature.py:118 +msgid "day" +msgstr "" + +#: perms/notifications.py:15 +msgid "You permed assets is about to expire" +msgstr "" + +#: perms/notifications.py:20 +msgid "permed assets" +msgstr "" + +#: perms/notifications.py:59 +msgid "Asset permissions is about to expire" +msgstr "" + +#: perms/notifications.py:64 +msgid "asset permissions of organization {}" +msgstr "" + +#: perms/serializers/permission.py:34 users/serializers/user.py:173 +msgid "Groups" +msgstr "" + +#: perms/serializers/permission.py:39 +msgid "Groups amount" +msgstr "" + +#: perms/tasks.py:27 +msgid "Check asset permission expired" +msgstr "" + +#: perms/tasks.py:40 +msgid "Send asset permission expired notification" +msgstr "" + +#: perms/templates/perms/_msg_item_permissions_expire.html:7 +#: perms/templates/perms/_msg_permed_items_expire.html:7 +#, python-format +msgid "" +"\n" +" The following %(item_type)s will expire in %(count)s\n" +" " +msgstr "" + +#: rbac/api/role.py:35 +msgid "Internal role, can't be destroy" +msgstr "" + +#: rbac/api/role.py:40 +msgid "The role has been bound to users, can't be destroy" +msgstr "" + +#: rbac/api/role.py:105 +msgid "Internal role, can't be update" +msgstr "" + +#: rbac/api/rolebinding.py:45 +msgid "{} at least one system role" +msgstr "" + +#: rbac/apps.py:7 +msgid "App RBAC" +msgstr "" + +#: rbac/builtin.py:115 +msgid "SystemAdmin" +msgstr "" + +#: rbac/builtin.py:118 +msgid "SystemAuditor" +msgstr "" + +#: rbac/builtin.py:121 +msgid "SystemComponent" +msgstr "" + +#: rbac/builtin.py:127 +msgid "OrgAdmin" +msgstr "" + +#: rbac/builtin.py:130 +msgid "OrgAuditor" +msgstr "" + +#: rbac/builtin.py:133 +msgid "OrgUser" +msgstr "" + +#: rbac/models/menu.py:13 +msgid "Menu permission" +msgstr "" + +#: rbac/models/menu.py:15 +msgid "Can view console view" +msgstr "" + +#: rbac/models/menu.py:16 +msgid "Can view audit view" +msgstr "" + +#: rbac/models/menu.py:17 +msgid "Can view workbench view" +msgstr "" + +#: rbac/models/menu.py:18 +msgid "Can view web terminal" +msgstr "" + +#: rbac/models/menu.py:19 +msgid "Can view file manager" +msgstr "" + +#: rbac/models/menu.py:20 +msgid "Can view System Tools" +msgstr "" + +#: rbac/models/permission.py:78 rbac/models/role.py:34 +msgid "Permissions" +msgstr "" + +#: rbac/models/role.py:31 rbac/models/rolebinding.py:46 +#: rbac/serializers/role.py:12 settings/serializers/auth/oauth2.py:36 +msgid "Scope" +msgstr "" + +#: rbac/models/role.py:46 rbac/models/rolebinding.py:52 +#: users/models/user.py:884 +msgid "Role" +msgstr "" + +#: rbac/models/role.py:144 +msgid "System role" +msgstr "" + +#: rbac/models/role.py:152 +msgid "Organization role" +msgstr "" + +#: rbac/models/rolebinding.py:62 +msgid "Role binding" +msgstr "" + +#: rbac/models/rolebinding.py:161 +msgid "All organizations" +msgstr "" + +#: rbac/models/rolebinding.py:193 +msgid "" +"User last role in org, can not be delete, you can remove user from org " +"instead" +msgstr "" + +#: rbac/models/rolebinding.py:200 +msgid "Organization role binding" +msgstr "" + +#: rbac/models/rolebinding.py:215 +msgid "System role binding" +msgstr "" + +#: rbac/serializers/permission.py:25 users/serializers/profile.py:108 +msgid "Perms" +msgstr "" + +#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:34 +#: terminal/models/virtualapp/virtualapp.py:20 +msgid "Display name" +msgstr "" + +#: rbac/serializers/rolebinding.py:60 +msgid "Has bound this role" +msgstr "" + +#: rbac/tree.py:17 rbac/tree.py:18 +msgid "All permissions" +msgstr "" + +#: rbac/tree.py:24 +msgid "Console view" +msgstr "" + +#: rbac/tree.py:25 +msgid "Workbench view" +msgstr "" + +#: rbac/tree.py:26 +msgid "Audit view" +msgstr "" + +#: rbac/tree.py:27 settings/models.py:161 +msgid "System setting" +msgstr "" + +#: rbac/tree.py:37 +msgid "Session audits" +msgstr "" + +#: rbac/tree.py:49 +msgid "Cloud import" +msgstr "" + +#: rbac/tree.py:50 +msgid "Backup account" +msgstr "" + +#: rbac/tree.py:51 +msgid "Gather account" +msgstr "" + +#: rbac/tree.py:53 +msgid "Asset change auth" +msgstr "" + +#: rbac/tree.py:54 +msgid "Terminal setting" +msgstr "" + +#: rbac/tree.py:55 settings/serializers/feature.py:127 +msgid "Job center" +msgstr "" + +#: rbac/tree.py:56 +msgid "My assets" +msgstr "" + +#: rbac/tree.py:57 +msgid "App ops" +msgstr "" + +#: rbac/tree.py:58 terminal/models/applet/applet.py:52 +#: terminal/models/applet/applet.py:317 terminal/models/applet/host.py:30 +#: terminal/serializers/applet.py:15 +msgid "Applet" +msgstr "" + +#: rbac/tree.py:128 +msgid "App organizations" +msgstr "" + +#: rbac/tree.py:129 +msgid "Ticket comment" +msgstr "" + +#: rbac/tree.py:130 settings/serializers/feature.py:109 +#: tickets/models/ticket/general.py:305 +msgid "Ticket" +msgstr "" + +#: rbac/tree.py:131 +msgid "Common setting" +msgstr "" + +#: rbac/tree.py:132 +msgid "View permission tree" +msgstr "" + +#: settings/api/chat.py:40 +msgid "Chat AI is not enabled" +msgstr "" + +#: settings/api/chat.py:79 settings/api/dingtalk.py:31 +#: settings/api/feishu.py:36 settings/api/slack.py:34 settings/api/sms.py:160 +#: settings/api/vault.py:40 settings/api/wecom.py:37 +msgid "Test success" +msgstr "" + +#: settings/api/email.py:22 +msgid "Test mail sent to {}, please check" +msgstr "" + +#: settings/api/ldap.py:89 +msgid "" +"Users are not synchronized, please click the user synchronization button" +msgstr "" + +#: settings/api/sms.py:142 +msgid "Invalid SMS platform" +msgstr "" + +#: settings/api/sms.py:148 +msgid "test_phone is required" +msgstr "" + +#: settings/apps.py:7 +msgid "App Settings" +msgstr "" + +#: settings/models.py:37 users/models/preference.py:14 +msgid "Encrypted" +msgstr "" + +#: settings/models.py:163 +msgid "Can change email setting" +msgstr "" + +#: settings/models.py:164 +msgid "Can change auth setting" +msgstr "" + +#: settings/models.py:165 +msgid "Can change auth ops" +msgstr "" + +#: settings/models.py:166 +msgid "Can change auth ticket" +msgstr "" + +#: settings/models.py:167 +msgid "Can change virtual app setting" +msgstr "" + +#: settings/models.py:168 +msgid "Can change auth announcement" +msgstr "" + +#: settings/models.py:169 +msgid "Can change vault setting" +msgstr "" + +#: settings/models.py:170 +msgid "Can change chat ai setting" +msgstr "" + +#: settings/models.py:171 +msgid "Can change system msg sub setting" +msgstr "" + +#: settings/models.py:172 +msgid "Can change sms setting" +msgstr "" + +#: settings/models.py:173 +msgid "Can change security setting" +msgstr "" + +#: settings/models.py:174 +msgid "Can change clean setting" +msgstr "" + +#: settings/models.py:175 +msgid "Can change interface setting" +msgstr "" + +#: settings/models.py:176 +msgid "Can change license setting" +msgstr "" + +#: settings/models.py:177 +msgid "Can change terminal setting" +msgstr "" + +#: settings/models.py:178 +msgid "Can change other setting" +msgstr "" + +#: settings/models.py:188 +msgid "Chat prompt" +msgstr "" + +#: settings/notifications.py:23 +msgid "Notification of Synchronized LDAP User Task Results" +msgstr "" + +#: settings/serializers/auth/base.py:10 +msgid "Authentication" +msgstr "" + +#: settings/serializers/auth/base.py:12 +msgid "LDAP Auth" +msgstr "" + +#: settings/serializers/auth/base.py:13 +msgid "CAS Auth" +msgstr "" + +#: settings/serializers/auth/base.py:14 +msgid "OPENID Auth" +msgstr "" + +#: settings/serializers/auth/base.py:15 +msgid "SAML2 Auth" +msgstr "" + +#: settings/serializers/auth/base.py:16 +msgid "OAuth2 Auth" +msgstr "" + +#: settings/serializers/auth/base.py:17 +msgid "RADIUS Auth" +msgstr "" + +#: settings/serializers/auth/base.py:18 +msgid "DingTalk Auth" +msgstr "" + +#: settings/serializers/auth/base.py:19 +msgid "FeiShu Auth" +msgstr "" + +#: settings/serializers/auth/base.py:20 +msgid "Lark Auth" +msgstr "" + +#: settings/serializers/auth/base.py:21 +msgid "Slack Auth" +msgstr "" + +#: settings/serializers/auth/base.py:22 +msgid "WeCom Auth" +msgstr "" + +#: settings/serializers/auth/base.py:23 +msgid "SSO Auth" +msgstr "" + +#: settings/serializers/auth/base.py:24 +msgid "Passkey Auth" +msgstr "" + +#: settings/serializers/auth/base.py:27 +msgid "Forgot Password URL" +msgstr "" + +#: settings/serializers/auth/base.py:30 +msgid "Login redirection prompt" +msgstr "" + +#: settings/serializers/auth/cas.py:10 settings/serializers/auth/cas.py:12 +msgid "CAS" +msgstr "" + +#: settings/serializers/auth/cas.py:13 settings/serializers/auth/ldap.py:42 +#: settings/serializers/auth/oidc.py:54 +msgid "Server" +msgstr "" + +#: settings/serializers/auth/cas.py:16 +msgid "Proxy Server" +msgstr "" + +#: settings/serializers/auth/cas.py:18 settings/serializers/auth/oauth2.py:54 +#: settings/serializers/auth/saml2.py:33 +msgid "Logout completely" +msgstr "" + +#: settings/serializers/auth/cas.py:23 +msgid "Username attr" +msgstr "" + +#: settings/serializers/auth/cas.py:26 +msgid "Enable attributes map" +msgstr "" + +#: settings/serializers/auth/cas.py:28 settings/serializers/auth/ldap.py:58 +#: settings/serializers/auth/oauth2.py:56 settings/serializers/auth/oidc.py:37 +#: settings/serializers/auth/saml2.py:32 +msgid "User attribute" +msgstr "" + +#: settings/serializers/auth/cas.py:30 +msgid "Create user" +msgstr "" + +#: settings/serializers/auth/cas.py:31 +msgid "Automatically create a new user if not found." +msgstr "" + +#: settings/serializers/auth/dingtalk.py:15 +msgid "Dingtalk" +msgstr "" + +#: settings/serializers/auth/feishu.py:12 +msgid "Enable FeiShu Auth" +msgstr "" + +#: settings/serializers/auth/lark.py:12 +msgid "Enable Lark Auth" +msgstr "" + +#: settings/serializers/auth/ldap.py:39 settings/serializers/auth/ldap.py:93 +msgid "LDAP" +msgstr "" + +#: settings/serializers/auth/ldap.py:43 +msgid "eg: ldap://localhost:389" +msgstr "" + +#: settings/serializers/auth/ldap.py:45 +msgid "Bind DN" +msgstr "" + +#: settings/serializers/auth/ldap.py:50 +msgid "User OU" +msgstr "" + +#: settings/serializers/auth/ldap.py:51 +msgid "Use | split multi OUs" +msgstr "" + +#: settings/serializers/auth/ldap.py:54 +msgid "User search filter" +msgstr "" + +#: settings/serializers/auth/ldap.py:55 +#, python-format +msgid "Choice may be (cn|uid|sAMAccountName)=%(user)s)" +msgstr "" + +#: settings/serializers/auth/ldap.py:59 +msgid "" +"User attr map present how to map LDAP user attr to jumpserver, username,name," +"email is jumpserver attr" +msgstr "" + +#: settings/serializers/auth/ldap.py:77 +msgid "Connect timeout (s)" +msgstr "" + +#: settings/serializers/auth/ldap.py:82 +msgid "User DN cache timeout (s)" +msgstr "" + +#: settings/serializers/auth/ldap.py:84 +msgid "" +"Caching the User DN obtained during user login authentication can " +"effectivelyimprove the speed of user authentication., 0 means no cache" +msgstr "" + +#: settings/serializers/auth/ldap.py:88 +msgid "Search paged size (piece)" +msgstr "" + +#: settings/serializers/auth/oauth2.py:18 +#: settings/serializers/auth/oauth2.py:21 +msgid "OAuth2" +msgstr "" + +#: settings/serializers/auth/oauth2.py:24 +msgid "Logo" +msgstr "" + +#: settings/serializers/auth/oauth2.py:27 +msgid "Service provider" +msgstr "" + +#: settings/serializers/auth/oauth2.py:30 settings/serializers/auth/oidc.py:19 +msgid "Client Id" +msgstr "" + +#: settings/serializers/auth/oauth2.py:33 settings/serializers/auth/oidc.py:22 +#: xpack/plugins/cloud/serializers/account_attrs.py:38 +msgid "Client Secret" +msgstr "" + +#: settings/serializers/auth/oauth2.py:39 settings/serializers/auth/oidc.py:68 +msgid "Authorization endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:42 settings/serializers/auth/oidc.py:71 +msgid "Token endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:45 settings/serializers/auth/oidc.py:30 +#: settings/serializers/auth/sms.py:106 +msgid "Request method" +msgstr "" + +#: settings/serializers/auth/oauth2.py:49 settings/serializers/auth/oidc.py:77 +msgid "Userinfo endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:52 settings/serializers/auth/oidc.py:80 +msgid "End session endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:59 settings/serializers/auth/oidc.py:98 +#: settings/serializers/auth/saml2.py:34 +msgid "Always update user" +msgstr "" + +#: settings/serializers/auth/oidc.py:12 settings/serializers/auth/oidc.py:63 +msgid "OIDC" +msgstr "" + +#: settings/serializers/auth/oidc.py:16 +msgid "Base site URL" +msgstr "" + +#: settings/serializers/auth/oidc.py:32 +msgid "Share session" +msgstr "" + +#: settings/serializers/auth/oidc.py:34 +msgid "Ignore SSL verification" +msgstr "" + +#: settings/serializers/auth/oidc.py:38 +msgid "" +"User attr map present how to map OpenID user attr to jumpserver, username," +"name,email is jumpserver attr" +msgstr "" + +#: settings/serializers/auth/oidc.py:41 +msgid "Enable PKCE" +msgstr "" + +#: settings/serializers/auth/oidc.py:43 +msgid "Code challenge method" +msgstr "" + +#: settings/serializers/auth/oidc.py:51 +msgid "Use Keycloak" +msgstr "" + +#: settings/serializers/auth/oidc.py:57 +msgid "Realm name" +msgstr "" + +#: settings/serializers/auth/oidc.py:65 +msgid "Provider endpoint" +msgstr "" + +#: settings/serializers/auth/oidc.py:74 +msgid "JWKS endpoint" +msgstr "" + +#: settings/serializers/auth/oidc.py:83 +msgid "Signature algorithm" +msgstr "" + +#: settings/serializers/auth/oidc.py:86 +msgid "Signing key" +msgstr "" + +#: settings/serializers/auth/oidc.py:88 +msgid "Scopes" +msgstr "" + +#: settings/serializers/auth/oidc.py:90 +msgid "ID Token max age (s)" +msgstr "" + +#: settings/serializers/auth/oidc.py:93 +msgid "ID Token include claims" +msgstr "" + +#: settings/serializers/auth/oidc.py:95 +msgid "Use state" +msgstr "" + +#: settings/serializers/auth/oidc.py:96 +msgid "Use nonce" +msgstr "" + +#: settings/serializers/auth/passkey.py:12 +msgid "Only SSL domain can use passkey auth" +msgstr "" + +#: settings/serializers/auth/passkey.py:15 +msgid "FIDO Server ID" +msgstr "" + +#: settings/serializers/auth/passkey.py:17 +msgid "" +"The hostname can using passkey auth, If not set, will use request host and " +"the request host in DOMAINS, If multiple domains, use comma to separate" +msgstr "" + +#: settings/serializers/auth/passkey.py:22 +msgid "FIDO Server name" +msgstr "" + +#: settings/serializers/auth/radius.py:13 +#: settings/serializers/auth/radius.py:15 +msgid "Radius" +msgstr "" + +#: settings/serializers/auth/radius.py:21 +msgid "OTP in Radius" +msgstr "" + +#: settings/serializers/auth/saml2.py:10 settings/serializers/auth/saml2.py:13 +msgid "SAML2" +msgstr "" + +#: settings/serializers/auth/saml2.py:16 +msgid "IDP Metadata URL" +msgstr "" + +#: settings/serializers/auth/saml2.py:19 +msgid "IDP Metadata XML" +msgstr "" + +#: settings/serializers/auth/saml2.py:22 +msgid "SP advanced settings" +msgstr "" + +#: settings/serializers/auth/saml2.py:26 +msgid "SP private key" +msgstr "" + +#: settings/serializers/auth/saml2.py:30 +msgid "SP cert" +msgstr "" + +#: settings/serializers/auth/sms.py:19 +msgid "SMS provider / Protocol" +msgstr "" + +#: settings/serializers/auth/sms.py:22 +msgid "SMS code length" +msgstr "" + +#: settings/serializers/auth/sms.py:27 settings/serializers/auth/sms.py:49 +#: settings/serializers/auth/sms.py:57 settings/serializers/auth/sms.py:66 +#: settings/serializers/auth/sms.py:77 settings/serializers/msg.py:83 +msgid "Signature" +msgstr "" + +#: settings/serializers/auth/sms.py:28 settings/serializers/auth/sms.py:50 +#: settings/serializers/auth/sms.py:58 settings/serializers/auth/sms.py:67 +msgid "Template code" +msgstr "" + +#: settings/serializers/auth/sms.py:35 +msgid "Test phone" +msgstr "" + +#: settings/serializers/auth/sms.py:64 +msgid "App Access Address" +msgstr "" + +#: settings/serializers/auth/sms.py:65 +msgid "Signature channel number" +msgstr "" + +#: settings/serializers/auth/sms.py:73 +msgid "Enterprise code" +msgstr "" + +#: settings/serializers/auth/sms.py:74 +msgid "Shared secret" +msgstr "" + +#: settings/serializers/auth/sms.py:75 +msgid "Original number" +msgstr "" + +#: settings/serializers/auth/sms.py:76 +msgid "Business type" +msgstr "" + +#: settings/serializers/auth/sms.py:80 +#, python-brace-format +msgid "" +"Template need contain {code} and Signature + template length does not exceed " +"67 words. For example, your verification code is {code}, which is valid for " +"5 minutes. Please do not disclose it to others." +msgstr "" + +#: settings/serializers/auth/sms.py:89 +#, python-brace-format +msgid "The template needs to contain {code}" +msgstr "" + +#: settings/serializers/auth/sms.py:92 +msgid "Signature + Template must not exceed 65 words" +msgstr "" + +#: settings/serializers/auth/sms.py:101 +msgid "URL" +msgstr "" + +#: settings/serializers/auth/sso.py:16 +msgid "Enable SSO auth" +msgstr "" + +#: settings/serializers/auth/sso.py:17 +msgid "Other service can using SSO token login to JumpServer without password" +msgstr "" + +#: settings/serializers/auth/sso.py:20 +msgid "SSO auth key TTL" +msgstr "" + +#: settings/serializers/auth/sso.py:20 +#: xpack/plugins/cloud/serializers/account_attrs.py:200 +msgid "Unit: second" +msgstr "" + +#: settings/serializers/basic.py:11 +msgid "Site URL" +msgstr "" + +#: settings/serializers/basic.py:13 +msgid "" +"External URL, email links or other system callbacks are used to access it, " +"eg: http://dev.jumpserver.org:8080" +msgstr "" + +#: settings/serializers/basic.py:18 +msgid "User guide url" +msgstr "" + +#: settings/serializers/basic.py:19 +msgid "User first login update profile done redirect to it" +msgstr "" + +#: settings/serializers/basic.py:22 +msgid "Global organization" +msgstr "" + +#: settings/serializers/basic.py:23 +msgid "The name of global organization to display" +msgstr "" + +#: settings/serializers/basic.py:26 +msgid "Help Docs URL" +msgstr "" + +#: settings/serializers/basic.py:27 +msgid "default: http://docs.jumpserver.org" +msgstr "" + +#: settings/serializers/basic.py:30 +msgid "Help Support URL" +msgstr "" + +#: settings/serializers/basic.py:31 +msgid "default: http://www.jumpserver.org/support/" +msgstr "" + +#: settings/serializers/basic.py:44 +msgid "Organization name already exists" +msgstr "" + +#: settings/serializers/cleaning.py:11 +msgid "Period clean" +msgstr "" + +#: settings/serializers/cleaning.py:15 +msgid "Login log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:19 +msgid "Task log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:23 +msgid "Operate log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:27 +msgid "password change log keep days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:31 +msgid "FTP log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:35 +msgid "Cloud sync task history retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:39 +msgid "job execution retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:43 +msgid "Activity log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:46 +msgid "Session log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:48 +msgid "" +"Session, record, command will be delete if more than duration, only in " +"database, OSS will not be affected." +msgstr "" + +#: settings/serializers/feature.py:18 settings/serializers/msg.py:68 +msgid "Subject" +msgstr "" + +#: settings/serializers/feature.py:22 +msgid "More URL" +msgstr "" + +#: settings/serializers/feature.py:36 settings/serializers/feature.py:38 +#: settings/serializers/feature.py:39 +msgid "Announcement" +msgstr "" + +#: settings/serializers/feature.py:46 +msgid "Vault" +msgstr "" + +#: settings/serializers/feature.py:55 +msgid "Mount Point" +msgstr "" + +#: settings/serializers/feature.py:60 +msgid "Historical accounts retained count" +msgstr "" + +#: settings/serializers/feature.py:62 +msgid "" +"If the specific value is less than 999, the system will automatically " +"perform a task every night: check and delete historical accounts that exceed " +"the predetermined number. If the value reaches or exceeds 999, no historical " +"account deletion will be performed." +msgstr "" + +#: settings/serializers/feature.py:71 settings/serializers/feature.py:75 +msgid "Chat AI" +msgstr "" + +#: settings/serializers/feature.py:78 +msgid "Base Url" +msgstr "" + +#: settings/serializers/feature.py:81 templates/_header_bar.html:96 +msgid "API Key" +msgstr "" + +#: settings/serializers/feature.py:87 +msgid "GPT Model" +msgstr "" + +#: settings/serializers/feature.py:111 +msgid "Enable tickets" +msgstr "" + +#: settings/serializers/feature.py:112 +msgid "No login approval" +msgstr "" + +#: settings/serializers/feature.py:115 +msgid "Default period" +msgstr "" + +#: settings/serializers/feature.py:118 +msgid "hour" +msgstr "" + +#: settings/serializers/feature.py:119 +msgid "Default unit" +msgstr "" + +#: settings/serializers/feature.py:124 +msgid "Feature" +msgstr "" + +#: settings/serializers/feature.py:128 +msgid "Allow user run batch command or not using ansible" +msgstr "" + +#: settings/serializers/feature.py:132 +msgid "Command blacklist" +msgstr "" + +#: settings/serializers/feature.py:133 +msgid "Commands that are not allowed execute." +msgstr "" + +#: settings/serializers/feature.py:138 settings/serializers/feature.py:141 +#: terminal/models/virtualapp/provider.py:17 +#: terminal/models/virtualapp/virtualapp.py:36 +#: terminal/models/virtualapp/virtualapp.py:97 +#: terminal/serializers/virtualapp.py:32 +msgid "Virtual app" +msgstr "" + +#: settings/serializers/msg.py:25 +msgid "SMTP" +msgstr "" + +#: settings/serializers/msg.py:26 +msgid "EXCHANGE" +msgstr "" + +#: settings/serializers/msg.py:36 +msgid "Tips: Some provider use token except password" +msgstr "" + +#: settings/serializers/msg.py:39 +msgid "Sender" +msgstr "" + +#: settings/serializers/msg.py:40 +msgid "Tips: Send mail account, default SMTP account as the send account" +msgstr "" + +#: settings/serializers/msg.py:43 +msgid "Test recipient" +msgstr "" + +#: settings/serializers/msg.py:44 +msgid "Tips: Used only as a test mail recipient" +msgstr "" + +#: settings/serializers/msg.py:48 +msgid "If SMTP port is 465, may be select" +msgstr "" + +#: settings/serializers/msg.py:51 +msgid "Use TLS" +msgstr "" + +#: settings/serializers/msg.py:52 +msgid "If SMTP port is 587, may be select" +msgstr "" + +#: settings/serializers/msg.py:55 +msgid "Subject prefix" +msgstr "" + +#: settings/serializers/msg.py:58 +msgid "Email suffix" +msgstr "" + +#: settings/serializers/msg.py:59 +msgid "" +"This is used by default if no email is returned during SSO authentication" +msgstr "" + +#: settings/serializers/msg.py:69 +msgid "" +"Tips: When creating a user, send the subject of the email (eg:Create account " +"successfully)" +msgstr "" + +#: settings/serializers/msg.py:73 +msgid "Honorific" +msgstr "" + +#: settings/serializers/msg.py:74 +msgid "Tips: When creating a user, send the honorific of the email (eg:Hello)" +msgstr "" + +#: settings/serializers/msg.py:80 +#, python-brace-format +msgid "" +"Tips: When creating a user, send the content of the email, support " +"{username} {name} {email} label" +msgstr "" + +#: settings/serializers/msg.py:84 +msgid "Tips: Email signature (eg:jumpserver)" +msgstr "" + +#: settings/serializers/other.py:8 +msgid "More..." +msgstr "" + +#: settings/serializers/other.py:11 +msgid "Perm ungroup node" +msgstr "" + +#: settings/serializers/other.py:12 +msgid "Perm single to ungroup node" +msgstr "" + +#: settings/serializers/security.py:17 +msgid "User password expiration (day)" +msgstr "" + +#: settings/serializers/security.py:19 +msgid "" +"If the user does not update the password during the time, the user password " +"will expire failure;The password expiration reminder mail will be automatic " +"sent to the user by system within 5 days (daily) before the password expires" +msgstr "" + +#: settings/serializers/security.py:26 +msgid "Recent password count" +msgstr "" + +#: settings/serializers/security.py:28 +msgid "" +"Tip: When the user resets the password, it cannot be the previous n " +"historical passwords of the user" +msgstr "" + +#: settings/serializers/security.py:34 +msgid "Minimum length (User)" +msgstr "" + +#: settings/serializers/security.py:38 +msgid "Minimum length (Admin)" +msgstr "" + +#: settings/serializers/security.py:47 +msgid "Digits" +msgstr "" + +#: settings/serializers/security.py:50 +msgid "Special characters" +msgstr "" + +#: settings/serializers/security.py:55 +msgid "" +"If the user has failed to log in for a limited number of times, no login is " +"allowed during this time interval." +msgstr "" + +#: settings/serializers/security.py:63 settings/serializers/security.py:73 +msgid "Login failures count" +msgstr "" + +#: settings/serializers/security.py:67 settings/serializers/security.py:77 +msgid "Login failure period (minute)" +msgstr "" + +#: settings/serializers/security.py:81 +msgid "Login IP whitelist" +msgstr "" + +#: settings/serializers/security.py:86 +msgid "Login IP blacklist" +msgstr "" + +#: settings/serializers/security.py:91 +msgid "Only single device login" +msgstr "" + +#: settings/serializers/security.py:92 +msgid "" +"After the user logs in on the new device, other logged-in devices will " +"automatically log out" +msgstr "" + +#: settings/serializers/security.py:95 +msgid "Only exist user login" +msgstr "" + +#: settings/serializers/security.py:97 +msgid "" +"If enabled, non-existent users will not be allowed to log in; if disabled, " +"users of other authentication methods except local authentication methods " +"are allowed to log in and automatically create users (if the user does not " +"exist)" +msgstr "" + +#: settings/serializers/security.py:103 +msgid "Only from source login" +msgstr "" + +#: settings/serializers/security.py:105 +msgid "" +"If it is enabled, the user will only authenticate to the source when logging " +"in; if it is disabled, the user will authenticate all the enabled " +"authentication methods in a certain order when logging in, and as long as " +"one of the authentication methods is successful, they can log in directly" +msgstr "" + +#: settings/serializers/security.py:116 +msgid "Not enabled" +msgstr "" + +#: settings/serializers/security.py:117 +msgid "All users" +msgstr "" + +#: settings/serializers/security.py:118 +msgid "Only admin users" +msgstr "" + +#: settings/serializers/security.py:120 +msgid "Global MFA auth" +msgstr "" + +#: settings/serializers/security.py:124 +msgid "Third-party login MFA" +msgstr "" + +#: settings/serializers/security.py:125 +msgid "The third-party login modes include OIDC, CAS, and SAML2" +msgstr "" + +#: settings/serializers/security.py:128 +msgid "OTP issuer name" +msgstr "" + +#: settings/serializers/security.py:132 +msgid "OTP valid window" +msgstr "" + +#: settings/serializers/security.py:136 +msgid "MFA verify TTL" +msgstr "" + +#: settings/serializers/security.py:138 +msgid "" +"Unit: second, The verification MFA takes effect only when you view the " +"account password" +msgstr "" + +#: settings/serializers/security.py:143 +msgid "MFA in login page" +msgstr "" + +#: settings/serializers/security.py:144 +msgid "Eu security regulations(GDPR) require MFA to be on the login page" +msgstr "" + +#: settings/serializers/security.py:148 +msgid "Verify code TTL (second)" +msgstr "" + +#: settings/serializers/security.py:149 +msgid "Reset password and send SMS code expiration time" +msgstr "" + +#: settings/serializers/security.py:153 +msgid "Login dynamic code" +msgstr "" + +#: settings/serializers/security.py:154 +msgid "" +"The password and additional code are sent to a third party authentication " +"system for verification" +msgstr "" + +#: settings/serializers/security.py:158 +msgid "Login captcha" +msgstr "" + +#: settings/serializers/security.py:159 +msgid "Enable captcha to prevent robot authentication" +msgstr "" + +#: settings/serializers/security.py:162 +msgid "Suspicious Login Verification" +msgstr "" + +#: settings/serializers/security.py:164 +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 " +"a remote login reminder" +msgstr "" + +#: settings/serializers/security.py:170 +msgid "Auto Disable Threshold (day)" +msgstr "" + +#: settings/serializers/security.py:171 +msgid "" +"Detect infrequent users daily and disable them if they exceed the " +"predetermined time limit." +msgstr "" + +#: settings/serializers/security.py:191 +msgid "Watermark" +msgstr "" + +#: settings/serializers/security.py:192 +msgid "Enabled, the web session and replay contains watermark information" +msgstr "" + +#: settings/serializers/security.py:196 +msgid "Max idle time (minute)" +msgstr "" + +#: settings/serializers/security.py:197 +msgid "If idle time more than it, disconnect connection." +msgstr "" + +#: settings/serializers/security.py:200 +msgid "Session expire at browser closed" +msgstr "" + +#: settings/serializers/security.py:201 +msgid "Whether to expire the session when the user closes their browser." +msgstr "" + +#: settings/serializers/security.py:205 +msgid "Max online time (hour)" +msgstr "" + +#: settings/serializers/security.py:206 +msgid "If session connection time more than it, disconnect connection." +msgstr "" + +#: settings/serializers/security.py:209 +msgid "Remember manual auth" +msgstr "" + +#: settings/serializers/security.py:212 +#: terminal/templates/terminal/_msg_session_sharing.html:10 +msgid "Session share" +msgstr "" + +#: settings/serializers/security.py:213 +msgid "Enabled, Allows user active session to be shared with other users" +msgstr "" + +#: settings/serializers/security.py:219 +msgid "Insecure command alert" +msgstr "" + +#: settings/serializers/security.py:222 +msgid "Email recipient" +msgstr "" + +#: settings/serializers/security.py:223 +msgid "Multiple user using , split" +msgstr "" + +#: settings/serializers/settings.py:62 +#, python-format +msgid "[%s] %s" +msgstr "" + +#: settings/serializers/terminal.py:15 +msgid "Auto" +msgstr "" + +#: settings/serializers/terminal.py:22 +msgid "Terminal registration" +msgstr "" + +#: settings/serializers/terminal.py:24 +msgid "" +"Allow terminal register, after all terminal setup, you should disable this " +"for security" +msgstr "" + +#: settings/serializers/terminal.py:27 +msgid "Password auth" +msgstr "" + +#: settings/serializers/terminal.py:29 +msgid "Public key auth" +msgstr "" + +#: settings/serializers/terminal.py:30 +msgid "" +"Information: If use other auth method, like AD/LDAP, you should disable this " +"to avoid being able to log in after deleting" +msgstr "" + +#: settings/serializers/terminal.py:34 +msgid "Asset list sorting" +msgstr "" + +#: settings/serializers/terminal.py:37 +msgid "Asset list page size" +msgstr "" + +#: settings/tasks/ldap.py:28 +msgid "Periodic import ldap user" +msgstr "" + +#: settings/tasks/ldap.py:66 +msgid "Registration periodic import ldap user task" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:2 +msgid "Sync task Finish" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:6 +#: terminal/models/session/session.py:46 +msgid "Date end" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:9 +msgid "Synced Organization" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:15 +msgid "Synced User" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:22 +msgid "No user synchronization required" +msgstr "" + +#: settings/utils/ldap.py:494 +msgid "ldap:// or ldaps:// protocol is used." +msgstr "" + +#: settings/utils/ldap.py:505 +msgid "Host or port is disconnected: {}" +msgstr "" + +#: settings/utils/ldap.py:507 +msgid "The port is not the port of the LDAP service: {}" +msgstr "" + +#: settings/utils/ldap.py:509 +msgid "Please add certificate: {}" +msgstr "" + +#: settings/utils/ldap.py:513 settings/utils/ldap.py:540 +#: settings/utils/ldap.py:570 settings/utils/ldap.py:598 +msgid "Unknown error: {}" +msgstr "" + +#: settings/utils/ldap.py:527 +msgid "Bind DN or Password incorrect" +msgstr "" + +#: settings/utils/ldap.py:534 +msgid "Please enter Bind DN: {}" +msgstr "" + +#: settings/utils/ldap.py:536 +msgid "Please enter Password: {}" +msgstr "" + +#: settings/utils/ldap.py:538 +msgid "Please enter correct Bind DN and Password: {}" +msgstr "" + +#: settings/utils/ldap.py:556 +msgid "Invalid User OU or User search filter: {}" +msgstr "" + +#: settings/utils/ldap.py:587 +msgid "LDAP User attr map not include: {}" +msgstr "" + +#: settings/utils/ldap.py:594 +msgid "LDAP User attr map is not dict" +msgstr "" + +#: settings/utils/ldap.py:613 +msgid "LDAP authentication is not enabled" +msgstr "" + +#: settings/utils/ldap.py:631 +msgid "Error (Invalid LDAP server): {}" +msgstr "" + +#: settings/utils/ldap.py:633 +msgid "Error (Invalid Bind DN): {}" +msgstr "" + +#: settings/utils/ldap.py:635 +msgid "Error (Invalid LDAP User attr map): {}" +msgstr "" + +#: settings/utils/ldap.py:637 +msgid "Error (Invalid User OU or User search filter): {}" +msgstr "" + +#: settings/utils/ldap.py:639 +msgid "Error (Not enabled LDAP authentication): {}" +msgstr "" + +#: settings/utils/ldap.py:641 +msgid "Error (Unknown): {}" +msgstr "" + +#: settings/utils/ldap.py:644 +msgid "Succeed: Match {} s user" +msgstr "" + +#: settings/utils/ldap.py:677 +msgid "Authentication failed (configuration incorrect): {}" +msgstr "" + +#: settings/utils/ldap.py:681 +msgid "Authentication failed (username or password incorrect): {}" +msgstr "" + +#: settings/utils/ldap.py:683 +msgid "Authentication failed (Unknown): {}" +msgstr "" + +#: settings/utils/ldap.py:686 +msgid "Authentication success: {}" +msgstr "" + +#: settings/ws.py:195 +msgid "Get ldap users is None" +msgstr "" + +#: settings/ws.py:205 +msgid "Imported {} users successfully (Organization: {})" +msgstr "" + +#: templates/_csv_import_export.html:8 +msgid "Export" +msgstr "" + +#: templates/_csv_import_export.html:13 templates/_csv_import_modal.html:5 +msgid "Import" +msgstr "" + +#: templates/_csv_import_modal.html:12 +msgid "Download the imported template or use the exported CSV file format" +msgstr "" + +#: templates/_csv_import_modal.html:13 +msgid "Download the import template" +msgstr "" + +#: templates/_csv_import_modal.html:17 templates/_csv_update_modal.html:17 +msgid "Select the CSV file to import" +msgstr "" + +#: templates/_csv_import_modal.html:39 templates/_csv_update_modal.html:42 +msgid "Please select file" +msgstr "" + +#: templates/_csv_update_modal.html:12 +msgid "Download the update template or use the exported CSV file format" +msgstr "" + +#: templates/_csv_update_modal.html:13 +msgid "Download the update template" +msgstr "" + +#: templates/_header_bar.html:12 +msgid "Help" +msgstr "" + +#: templates/_header_bar.html:19 +msgid "Docs" +msgstr "" + +#: templates/_header_bar.html:27 +msgid "Commercial support" +msgstr "" + +#: templates/_header_bar.html:85 users/forms/profile.py:43 +msgid "Profile" +msgstr "" + +#: templates/_header_bar.html:89 +msgid "Admin page" +msgstr "" + +#: templates/_header_bar.html:92 +msgid "User page" +msgstr "" + +#: templates/_header_bar.html:97 +msgid "Logout" +msgstr "" + +#: templates/_message.html:6 +msgid "" +"\n" +" Your account has expired, please contact the administrator.\n" +" " +msgstr "" + +#: templates/_message.html:13 +msgid "Your account will at" +msgstr "" + +#: templates/_message.html:13 templates/_message.html:30 +msgid "expired. " +msgstr "" + +#: templates/_message.html:23 +#, python-format +msgid "" +"\n" +" Your password has expired, please click this link update password.\n" +" " +msgstr "" + +#: templates/_message.html:30 +msgid "Your password will at" +msgstr "" + +#: templates/_message.html:31 +#, python-format +msgid "" +"\n" +" please click this " +"link to update your password.\n" +" " +msgstr "" + +#: templates/_message.html:43 +#, python-format +msgid "" +"\n" +" Your information was incomplete. Please click this link to complete your information.\n" +" " +msgstr "" + +#: templates/_message.html:56 +#, python-format +msgid "" +"\n" +" Your ssh public key not set or expired. Please click this link to update\n" +" " +msgstr "" + +#: templates/_mfa_login_field.html:28 +msgid "Send verification code" +msgstr "" + +#: templates/_mfa_login_field.html:107 +#: users/templates/users/forgot_password.html:176 +msgid "Wait: " +msgstr "" + +#: templates/_mfa_login_field.html:117 +#: users/templates/users/forgot_password.html:192 +msgid "The verification code has been sent" +msgstr "" + +#: templates/_without_nav_base.html:26 +msgid "Home page" +msgstr "" + +#: templates/resource_download.html:18 templates/resource_download.html:33 +#: users/const.py:65 +msgid "Client" +msgstr "" + +#: templates/resource_download.html:20 +msgid "" +"JumpServer Client, currently used to launch the client, now only support " +"launch RDP SSH client, The Telnet client will next" +msgstr "" + +#: templates/resource_download.html:33 +msgid "Microsoft" +msgstr "" + +#: templates/resource_download.html:33 +msgid "Official" +msgstr "" + +#: templates/resource_download.html:35 +msgid "" +"macOS needs to download the client to connect RDP asset, which comes with " +"Windows" +msgstr "" + +#: templates/resource_download.html:44 +msgid "Windows Remote application publisher tools" +msgstr "" + +#: templates/resource_download.html:45 +msgid "" +"OpenSSH is a program used to connect remote applications in the Windows " +"Remote Application Publisher" +msgstr "" + +#: templates/resource_download.html:53 +msgid "Offline video player" +msgstr "" + +#: terminal/api/applet/applet.py:52 terminal/api/applet/applet.py:55 +#: terminal/api/virtualapp/virtualapp.py:43 +#: terminal/api/virtualapp/virtualapp.py:46 +msgid "Invalid zip file" +msgstr "" + +#: terminal/api/applet/applet.py:74 +msgid "This is enterprise edition applet" +msgstr "" + +#: terminal/api/component/endpoint.py:32 +msgid "Not found protocol query params" +msgstr "" + +#: terminal/api/component/storage.py:31 +msgid "Deleting the default storage is not allowed" +msgstr "" + +#: terminal/api/component/storage.py:34 +msgid "Cannot delete storage that is being used" +msgstr "" + +#: terminal/api/component/storage.py:75 terminal/api/component/storage.py:76 +msgid "Command storages" +msgstr "" + +#: terminal/api/component/storage.py:82 +msgid "Invalid" +msgstr "" + +#: terminal/api/component/storage.py:130 terminal/tasks.py:149 +msgid "Test failure: {}" +msgstr "" + +#: terminal/api/component/storage.py:133 +msgid "Test successful" +msgstr "" + +#: terminal/api/component/storage.py:135 +msgid "Test failure: Please check configuration" +msgstr "" + +#: terminal/api/component/terminal.py:55 +msgid "Have online sessions" +msgstr "" + +#: terminal/api/session/session.py:48 +#, python-format +msgid "User %s %s session %s replay" +msgstr "" + +#: terminal/api/session/session.py:317 +msgid "Session does not exist: {}" +msgstr "" + +#: terminal/api/session/session.py:320 +msgid "Session is finished or the protocol not supported" +msgstr "" + +#: terminal/api/session/session.py:333 +msgid "User does not have permission" +msgstr "" + +#: terminal/api/session/sharing.py:29 +msgid "Secure session sharing settings is disabled" +msgstr "" + +#: terminal/apps.py:9 +msgid "App Terminals" +msgstr "" + +#: terminal/backends/command/models.py:19 +msgid "Input" +msgstr "" + +#: terminal/backends/command/models.py:20 terminal/serializers/command.py:73 +msgid "Output" +msgstr "" + +#: terminal/backends/command/models.py:24 terminal/serializers/command.py:22 +#: terminal/templates/terminal/_msg_command_warning.html:10 +msgid "Risk level" +msgstr "" + +#: terminal/connect_methods.py:29 +msgid "SSH Client" +msgstr "" + +#: terminal/connect_methods.py:30 +msgid "SSH Guide" +msgstr "" + +#: terminal/connect_methods.py:31 +msgid "SFTP Client" +msgstr "" + +#: terminal/connect_methods.py:33 +msgid "DB Guide" +msgstr "" + +#: terminal/connect_methods.py:34 +msgid "DB Client" +msgstr "" + +#: terminal/connect_methods.py:36 +msgid "Remote Desktop" +msgstr "" + +#: terminal/connect_methods.py:37 +msgid "RDP Guide" +msgstr "" + +#: terminal/const.py:10 +msgid "Warning" +msgstr "" + +#: terminal/const.py:12 +msgid "Review & Reject" +msgstr "" + +#: terminal/const.py:13 +msgid "Review & Accept" +msgstr "" + +#: terminal/const.py:14 +msgid "Review & Cancel" +msgstr "" + +#: terminal/const.py:45 +msgid "Critical" +msgstr "" + +#: terminal/const.py:46 +msgid "High" +msgstr "" + +#: terminal/const.py:47 terminal/const.py:84 +#: users/templates/users/reset_password.html:50 +msgid "Normal" +msgstr "" + +#: terminal/const.py:48 +msgid "Offline" +msgstr "" + +#: terminal/const.py:80 +msgid "Mismatch" +msgstr "" + +#: terminal/const.py:85 +msgid "Tunnel" +msgstr "" + +#: terminal/const.py:91 +msgid "Read only" +msgstr "" + +#: terminal/const.py:92 +msgid "Writable" +msgstr "" + +#: terminal/const.py:96 +msgid "Kill session" +msgstr "" + +#: terminal/const.py:97 +msgid "Lock session" +msgstr "" + +#: terminal/const.py:98 +msgid "Unlock session" +msgstr "" + +#: terminal/const.py:103 +msgid "Replay create failed" +msgstr "" + +#: terminal/const.py:104 +msgid "Replay upload failed" +msgstr "" + +#: terminal/const.py:105 +msgid "Replay convert failed" +msgstr "" + +#: terminal/const.py:106 +msgid "Replay unsupported" +msgstr "" + +#: terminal/exceptions.py:8 +msgid "Bulk create not support" +msgstr "" + +#: terminal/exceptions.py:13 +msgid "Storage is invalid" +msgstr "" + +#: terminal/models/applet/applet.py:30 xpack/plugins/license/models.py:88 +msgid "Community edition" +msgstr "" + +#: terminal/models/applet/applet.py:31 +msgid "Enterprise" +msgstr "" + +#: terminal/models/applet/applet.py:36 +#: terminal/models/virtualapp/virtualapp.py:22 +msgid "Author" +msgstr "" + +#: terminal/models/applet/applet.py:38 terminal/serializers/applet.py:31 +msgid "Edition" +msgstr "" + +#: terminal/models/applet/applet.py:43 +msgid "Can concurrent" +msgstr "" + +#: terminal/models/applet/applet.py:44 +#: terminal/models/virtualapp/virtualapp.py:29 +msgid "Tags" +msgstr "" + +#: terminal/models/applet/applet.py:48 terminal/serializers/applet_host.py:167 +#: terminal/serializers/storage.py:197 +msgid "Hosts" +msgstr "" + +#: terminal/models/applet/applet.py:93 +#: terminal/models/virtualapp/virtualapp.py:66 +msgid "Applet pkg not valid, Missing file {}" +msgstr "" + +#: terminal/models/applet/applet.py:112 +msgid "Load platform.yml failed: {}" +msgstr "" + +#: terminal/models/applet/applet.py:115 +msgid "Only support custom platform" +msgstr "" + +#: terminal/models/applet/applet.py:120 +msgid "Missing type in platform.yml" +msgstr "" + +#: terminal/models/applet/applet.py:319 terminal/models/applet/host.py:36 +#: terminal/models/applet/host.py:138 +msgid "Hosting" +msgstr "" + +#: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:69 +msgid "Deploy options" +msgstr "" + +#: terminal/models/applet/host.py:19 +msgid "Auto create accounts" +msgstr "" + +#: terminal/models/applet/host.py:20 +msgid "Accounts create amount" +msgstr "" + +#: terminal/models/applet/host.py:21 +msgid "Inited" +msgstr "" + +#: terminal/models/applet/host.py:22 +msgid "Date inited" +msgstr "" + +#: terminal/models/applet/host.py:23 +msgid "Date synced" +msgstr "" + +#: terminal/models/applet/host.py:28 +msgid "Using same account" +msgstr "" + +#: terminal/models/applet/host.py:139 +msgid "Initial" +msgstr "" + +#: terminal/models/component/endpoint.py:15 +msgid "HTTPS port" +msgstr "" + +#: terminal/models/component/endpoint.py:16 +msgid "HTTP port" +msgstr "" + +#: terminal/models/component/endpoint.py:17 +msgid "SSH port" +msgstr "" + +#: terminal/models/component/endpoint.py:18 +msgid "RDP port" +msgstr "" + +#: terminal/models/component/endpoint.py:19 +msgid "MySQL port" +msgstr "" + +#: terminal/models/component/endpoint.py:20 +msgid "MariaDB port" +msgstr "" + +#: terminal/models/component/endpoint.py:21 +msgid "PostgreSQL port" +msgstr "" + +#: terminal/models/component/endpoint.py:22 +msgid "Redis port" +msgstr "" + +#: terminal/models/component/endpoint.py:23 +msgid "SQLServer port" +msgstr "" + +#: terminal/models/component/endpoint.py:30 +#: terminal/models/component/endpoint.py:117 +#: terminal/serializers/endpoint.py:73 terminal/serializers/storage.py:41 +#: terminal/serializers/storage.py:53 terminal/serializers/storage.py:83 +#: terminal/serializers/storage.py:93 terminal/serializers/storage.py:101 +msgid "Endpoint" +msgstr "" + +#: terminal/models/component/endpoint.py:123 +msgid "Endpoint rule" +msgstr "" + +#: terminal/models/component/status.py:15 +msgid "Session Online" +msgstr "" + +#: terminal/models/component/status.py:16 +msgid "CPU Load" +msgstr "" + +#: terminal/models/component/status.py:17 +msgid "Memory Used" +msgstr "" + +#: terminal/models/component/status.py:18 +msgid "Disk Used" +msgstr "" + +#: terminal/models/component/status.py:19 +msgid "Connections" +msgstr "" + +#: terminal/models/component/status.py:20 +msgid "Threads" +msgstr "" + +#: terminal/models/component/status.py:21 +msgid "Boot Time" +msgstr "" + +#: terminal/models/component/storage.py:28 +msgid "Default storage" +msgstr "" + +#: terminal/models/component/storage.py:140 +#: terminal/models/component/terminal.py:91 +msgid "Command storage" +msgstr "" + +#: terminal/models/component/storage.py:204 +#: terminal/models/component/terminal.py:92 +msgid "Replay storage" +msgstr "" + +#: terminal/models/component/terminal.py:88 +msgid "type" +msgstr "" + +#: terminal/models/component/terminal.py:90 terminal/serializers/command.py:76 +msgid "Remote Address" +msgstr "" + +#: terminal/models/component/terminal.py:93 +msgid "Application User" +msgstr "" + +#: terminal/models/component/terminal.py:177 +msgid "Can view terminal config" +msgstr "" + +#: terminal/models/session/command.py:76 +msgid "Command record" +msgstr "" + +#: terminal/models/session/replay.py:12 +msgid "Session replay" +msgstr "" + +#: terminal/models/session/replay.py:14 +msgid "Can upload session replay" +msgstr "" + +#: terminal/models/session/replay.py:15 +msgid "Can download session replay" +msgstr "" + +#: terminal/models/session/session.py:35 +msgid "Account ID" +msgstr "" + +#: terminal/models/session/session.py:37 terminal/models/session/sharing.py:118 +msgid "Login from" +msgstr "" + +#: terminal/models/session/session.py:42 +msgid "Replay" +msgstr "" + +#: terminal/models/session/session.py:48 terminal/serializers/session.py:68 +msgid "Command amount" +msgstr "" + +#: terminal/models/session/session.py:49 terminal/serializers/session.py:30 +msgid "Error reason" +msgstr "" + +#: terminal/models/session/session.py:290 +msgid "Session record" +msgstr "" + +#: terminal/models/session/session.py:292 +msgid "Can monitor session" +msgstr "" + +#: terminal/models/session/session.py:293 +msgid "Can share session" +msgstr "" + +#: terminal/models/session/session.py:294 +msgid "Can terminate session" +msgstr "" + +#: terminal/models/session/session.py:295 +msgid "Can validate session action perm" +msgstr "" + +#: terminal/models/session/sharing.py:32 +msgid "Expired time (min)" +msgstr "" + +#: terminal/models/session/sharing.py:36 terminal/serializers/sharing.py:20 +#: terminal/serializers/sharing.py:52 +msgid "Action permission" +msgstr "" + +#: terminal/models/session/sharing.py:38 +msgid "Origin" +msgstr "" + +#: terminal/models/session/sharing.py:42 terminal/models/session/sharing.py:100 +#: terminal/notifications.py:261 +msgid "Session sharing" +msgstr "" + +#: terminal/models/session/sharing.py:44 +msgid "Can add super session sharing" +msgstr "" + +#: terminal/models/session/sharing.py:83 +msgid "Link not active" +msgstr "" + +#: terminal/models/session/sharing.py:85 +msgid "Link expired" +msgstr "" + +#: terminal/models/session/sharing.py:87 +msgid "User not allowed to join" +msgstr "" + +#: terminal/models/session/sharing.py:104 terminal/serializers/sharing.py:71 +msgid "Joiner" +msgstr "" + +#: terminal/models/session/sharing.py:107 +msgid "Date joined" +msgstr "" + +#: terminal/models/session/sharing.py:110 +msgid "Date left" +msgstr "" + +#: terminal/models/session/sharing.py:133 +msgid "Session join record" +msgstr "" + +#: terminal/models/session/sharing.py:149 +msgid "Invalid verification code" +msgstr "" + +#: terminal/models/session/sharing.py:156 +msgid "You have already joined this session" +msgstr "" + +#: terminal/models/virtualapp/provider.py:11 +msgid "Hostname" +msgstr "" + +#: terminal/models/virtualapp/virtualapp.py:32 +msgid "Providers" +msgstr "" + +#: terminal/models/virtualapp/virtualapp.py:94 +#: terminal/serializers/virtualapp.py:34 +msgid "App Provider" +msgstr "" + +#: terminal/models/virtualapp/virtualapp.py:102 +msgid "Virtual app publication" +msgstr "" + +#: terminal/notifications.py:25 +msgid "Sessions" +msgstr "" + +#: terminal/notifications.py:72 +msgid "Command warning" +msgstr "" + +#: terminal/notifications.py:130 terminal/notifications.py:175 +msgid "Command reject" +msgstr "" + +#: terminal/notifications.py:157 terminal/notifications.py:206 +msgid "Level" +msgstr "" + +#: terminal/notifications.py:224 +msgid "Command and replay storage" +msgstr "" + +#: terminal/notifications.py:240 terminal/tasks.py:153 +msgid "Test failure: Account invalid" +msgstr "" + +#: terminal/notifications.py:250 +#: terminal/templates/terminal/_msg_check_command_replay_storage_connectivity.html:4 +msgid "Invalid storage" +msgstr "" + +#: terminal/serializers/applet.py:28 terminal/serializers/virtualapp.py:15 +msgid "Icon" +msgstr "" + +#: terminal/serializers/applet_host.py:24 +msgid "Per Session" +msgstr "" + +#: terminal/serializers/applet_host.py:25 +msgid "Per Device" +msgstr "" + +#: terminal/serializers/applet_host.py:37 +msgid "Core API" +msgstr "" + +#: terminal/serializers/applet_host.py:38 +msgid "" +" \n" +" Tips: The application release machine communicates with the Core " +"service. \n" +" If the release machine and the Core service are on the same network " +"segment, \n" +" it is recommended to fill in the intranet address, otherwise fill in " +"the current site URL \n" +"
\n" +" eg: https://172.16.10.110 or https://dev.jumpserver.com\n" +" " +msgstr "" + +#: terminal/serializers/applet_host.py:46 terminal/serializers/storage.py:208 +msgid "Ignore Certificate Verification" +msgstr "" + +#: terminal/serializers/applet_host.py:47 +msgid "Existing RDS license" +msgstr "" + +#: terminal/serializers/applet_host.py:48 +msgid "RDS License Server" +msgstr "" + +#: terminal/serializers/applet_host.py:49 +msgid "RDS Licensing Mode" +msgstr "" + +#: terminal/serializers/applet_host.py:51 +msgid "RDS Single Session Per User" +msgstr "" + +#: terminal/serializers/applet_host.py:53 +msgid "RDS Max Disconnection Time (ms)" +msgstr "" + +#: terminal/serializers/applet_host.py:55 +msgid "" +"Tips: Set the maximum duration for keeping a disconnected session active on " +"the server (log off the session after 60000 milliseconds)." +msgstr "" + +#: terminal/serializers/applet_host.py:60 +msgid "RDS Remote App Logoff Time Limit (ms)" +msgstr "" + +#: terminal/serializers/applet_host.py:62 +msgid "" +"Tips: Set the logoff time for RemoteApp sessions after closing all RemoteApp " +"programs (0 milliseconds, log off the session immediately)." +msgstr "" + +#: terminal/serializers/applet_host.py:71 terminal/serializers/terminal.py:47 +#: terminal/serializers/virtualapp_provider.py:13 +msgid "Load status" +msgstr "" + +#: terminal/serializers/applet_host.py:85 +msgid "" +"These accounts are used to connect to the published application, the account " +"is now divided into two types, one is dedicated to each account, each user " +"has a private account, the other is public, when the application does not " +"support multiple open and the special has been used, the public account will " +"be used to connect" +msgstr "" + +#: terminal/serializers/applet_host.py:92 +msgid "The number of public accounts created automatically" +msgstr "" + +#: terminal/serializers/applet_host.py:95 +msgid "" +"Connect to the host using the same account first. For security reasons, " +"please set the configuration item CACHE_LOGIN_PASSWORD_ENABLED=true and " +"restart the service to enable it." +msgstr "" + +#: terminal/serializers/applet_host.py:137 +msgid "Install applets" +msgstr "" + +#: terminal/serializers/applet_host.py:167 +msgid "Host ID" +msgstr "" + +#: terminal/serializers/applet_host.py:168 +msgid "Applet ID" +msgstr "" + +#: terminal/serializers/command.py:19 +msgid "Session ID" +msgstr "" + +#: terminal/serializers/command.py:41 +msgid "Command Filter ACL" +msgstr "" + +#: terminal/serializers/command.py:44 +msgid "Command Group" +msgstr "" + +#: terminal/serializers/command.py:55 +msgid "Invalid command filter ACL id" +msgstr "" + +#: terminal/serializers/command.py:59 +msgid "Invalid command group id" +msgstr "" + +#: terminal/serializers/command.py:63 +msgid "Invalid session id" +msgstr "" + +#: terminal/serializers/command.py:74 +msgid "Timestamp" +msgstr "" + +#: terminal/serializers/endpoint.py:15 +msgid "Oracle port" +msgstr "" + +#: terminal/serializers/endpoint.py:18 +msgid "Oracle port range" +msgstr "" + +#: terminal/serializers/endpoint.py:20 +msgid "" +"Oracle proxy server listen port is dynamic, Each additional Oracle database " +"instance adds a port listener" +msgstr "" + +#: terminal/serializers/endpoint.py:38 +msgid "" +"The host address accessed when connecting to assets, if it is empty, the " +"access address of the current browser will be used (the default endpoint " +"does not allow modification of the host)" +msgstr "" + +#: terminal/serializers/endpoint.py:64 +msgid "" +"The assets within this IP range, the following endpoint will be used for the " +"connection" +msgstr "" + +#: terminal/serializers/endpoint.py:65 +msgid "" +"If asset IP addresses under different endpoints conflict, use asset labels" +msgstr "" + +#: terminal/serializers/endpoint.py:69 +msgid "Asset IP" +msgstr "" + +#: terminal/serializers/session.py:25 terminal/serializers/session.py:53 +msgid "Can replay" +msgstr "" + +#: terminal/serializers/session.py:26 terminal/serializers/session.py:54 +msgid "Can join" +msgstr "" + +#: terminal/serializers/session.py:27 terminal/serializers/session.py:57 +msgid "Can terminate" +msgstr "" + +#: terminal/serializers/session.py:47 +msgid "Duration" +msgstr "" + +#: terminal/serializers/session.py:49 +msgid "User ID" +msgstr "" + +#: terminal/serializers/session.py:50 +msgid "Asset ID" +msgstr "" + +#: terminal/serializers/session.py:51 +msgid "Login from display" +msgstr "" + +#: terminal/serializers/session.py:58 +msgid "Terminal display" +msgstr "" + +#: terminal/serializers/storage.py:23 +msgid "Endpoint invalid: remove path `{}`" +msgstr "" + +#: terminal/serializers/storage.py:29 +msgid "Bucket" +msgstr "" + +#: terminal/serializers/storage.py:33 +msgid "Access key ID" +msgstr "" + +#: terminal/serializers/storage.py:37 +#: xpack/plugins/cloud/serializers/account_attrs.py:20 +msgid "Access key secret" +msgstr "" + +#: terminal/serializers/storage.py:68 xpack/plugins/cloud/models.py:253 +msgid "Region" +msgstr "" + +#: terminal/serializers/storage.py:112 +msgid "Container name" +msgstr "" + +#: terminal/serializers/storage.py:115 +msgid "Account key" +msgstr "" + +#: terminal/serializers/storage.py:118 +msgid "Endpoint suffix" +msgstr "" + +#: terminal/serializers/storage.py:129 +msgid "HOST" +msgstr "" + +#: terminal/serializers/storage.py:146 users/models/user.py:904 +#: xpack/plugins/cloud/serializers/account_attrs.py:213 +msgid "Private key" +msgstr "" + +#: terminal/serializers/storage.py:152 +msgid "SFTP Root" +msgstr "" + +#: terminal/serializers/storage.py:173 +msgid "The address cannot contain the special character `#`" +msgstr "" + +#: terminal/serializers/storage.py:175 +msgid "The address format is incorrect" +msgstr "" + +#: terminal/serializers/storage.py:182 +msgid "Host invalid" +msgstr "" + +#: terminal/serializers/storage.py:185 +msgid "Port invalid" +msgstr "" + +#: terminal/serializers/storage.py:200 +msgid "Index by date" +msgstr "" + +#: terminal/serializers/storage.py:201 +msgid "Whether to create an index by date" +msgstr "" + +#: terminal/serializers/storage.py:204 +msgid "Index" +msgstr "" + +#: terminal/serializers/storage.py:206 +msgid "Doc type" +msgstr "" + +#: terminal/serializers/task.py:9 +msgid "Session id" +msgstr "" + +#: terminal/serializers/terminal.py:42 +msgid "Online sessions" +msgstr "" + +#: terminal/serializers/terminal.py:43 +msgid "Is alive" +msgstr "" + +#: terminal/serializers/terminal.py:49 +msgid "Stat" +msgstr "" + +#: terminal/serializers/terminal.py:83 terminal/serializers/terminal.py:91 +msgid "Not found" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:26 +msgid "Container ID" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:27 +msgid "Container Image" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:28 +msgid "Container Name" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:29 +msgid "Container Status" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:30 +msgid "Container Ports" +msgstr "" + +#: terminal/session_lifecycle.py:30 +#, python-format +msgid "Connect to asset %s success" +msgstr "" + +#: terminal/session_lifecycle.py:38 +#, python-format +msgid "Connect to asset %s finished: %s" +msgstr "" + +#: terminal/session_lifecycle.py:48 +#, python-format +msgid "User %s create share link" +msgstr "" + +#: terminal/session_lifecycle.py:57 +#, python-format +msgid "User %s join session" +msgstr "" + +#: terminal/session_lifecycle.py:69 +#, python-format +msgid "User %s leave session" +msgstr "" + +#: terminal/session_lifecycle.py:81 +#, python-format +msgid "User %s join to monitor session" +msgstr "" + +#: terminal/session_lifecycle.py:93 +#, python-format +msgid "User %s exit to monitor session" +msgstr "" + +#: terminal/session_lifecycle.py:105 +msgid "Replay start to convert" +msgstr "" + +#: terminal/session_lifecycle.py:113 +msgid "Replay successfully converted to MP4 format" +msgstr "" + +#: terminal/session_lifecycle.py:121 +#, python-format +msgid "Replay failed to convert to MP4 format: %s" +msgstr "" + +#: terminal/session_lifecycle.py:129 +msgid "Replay start to upload" +msgstr "" + +#: terminal/session_lifecycle.py:137 +msgid "Replay successfully uploaded" +msgstr "" + +#: terminal/session_lifecycle.py:145 +#, python-format +msgid "Replay failed to upload: %s" +msgstr "" + +#: terminal/session_lifecycle.py:152 +msgid "connect failed" +msgstr "" + +#: terminal/session_lifecycle.py:153 +msgid "connection disconnect" +msgstr "" + +#: terminal/session_lifecycle.py:154 +msgid "user closed" +msgstr "" + +#: terminal/session_lifecycle.py:155 +msgid "idle disconnect" +msgstr "" + +#: terminal/session_lifecycle.py:156 +msgid "admin terminated" +msgstr "" + +#: terminal/session_lifecycle.py:157 +msgid "maximum session time has been reached" +msgstr "" + +#: terminal/session_lifecycle.py:158 +msgid "permission has expired" +msgstr "" + +#: terminal/session_lifecycle.py:159 +msgid "storage is null" +msgstr "" + +#: terminal/tasks.py:31 +msgid "Periodic delete terminal status" +msgstr "" + +#: terminal/tasks.py:39 +msgid "Clean orphan session" +msgstr "" + +#: terminal/tasks.py:87 +msgid "Run applet host deployment" +msgstr "" + +#: terminal/tasks.py:97 +msgid "Install applet" +msgstr "" + +#: terminal/tasks.py:108 +msgid "Uninstall applet" +msgstr "" + +#: terminal/tasks.py:119 +msgid "Generate applet host accounts" +msgstr "" + +#: terminal/tasks.py:131 +msgid "Check command replay storage connectivity" +msgstr "" + +#: terminal/templates/terminal/_msg_command_alert.html:10 +msgid "view" +msgstr "" + +#: terminal/utils/db_port_mapper.py:85 +msgid "" +"No available port is matched. The number of databases may have exceeded the " +"number of ports open to the database agent service, Contact the " +"administrator to open more ports." +msgstr "" + +#: terminal/utils/db_port_mapper.py:113 +msgid "" +"No ports can be used, check and modify the limit on the number of ports that " +"Magnus listens on in the configuration file." +msgstr "" + +#: terminal/utils/db_port_mapper.py:115 +msgid "All available port count: {}, Already use port count: {}" +msgstr "" + +#: tickets/api/ticket.py:88 tickets/models/ticket/general.py:286 +msgid "Applicant" +msgstr "" + +#: tickets/apps.py:7 +msgid "App Tickets" +msgstr "" + +#: tickets/const.py:10 +msgid "Apply for asset" +msgstr "" + +#: tickets/const.py:17 tickets/const.py:24 tickets/const.py:42 +msgid "Open" +msgstr "" + +#: tickets/const.py:19 tickets/const.py:31 +msgid "Approved" +msgstr "" + +#: tickets/const.py:20 tickets/const.py:32 +msgid "Rejected" +msgstr "" + +#: tickets/const.py:30 tickets/const.py:37 +msgid "Closed" +msgstr "" + +#: tickets/const.py:49 +msgid "One level" +msgstr "" + +#: tickets/const.py:50 +msgid "Two level" +msgstr "" + +#: tickets/const.py:54 +msgid "Org admin" +msgstr "" + +#: tickets/const.py:55 +msgid "Custom user" +msgstr "" + +#: tickets/const.py:56 +msgid "Super admin" +msgstr "" + +#: tickets/const.py:57 +msgid "Super admin and org admin" +msgstr "" + +#: tickets/const.py:61 +msgid "All assets" +msgstr "" + +#: tickets/const.py:62 +msgid "Permed assets" +msgstr "" + +#: tickets/const.py:63 +msgid "Permed valid assets" +msgstr "" + +#: tickets/errors.py:9 +msgid "Ticket already closed" +msgstr "" + +#: tickets/handlers/apply_asset.py:36 +msgid "" +"Created by the ticket ticket title: {} ticket applicant: {} ticket " +"processor: {} ticket ID: {}" +msgstr "" + +#: tickets/handlers/base.py:85 +msgid "Change field" +msgstr "" + +#: tickets/handlers/base.py:85 +msgid "Before change" +msgstr "" + +#: tickets/handlers/base.py:85 +msgid "After change" +msgstr "" + +#: tickets/handlers/base.py:97 +msgid "{} {} the ticket" +msgstr "" + +#: tickets/models/comment.py:14 +msgid "common" +msgstr "" + +#: tickets/models/comment.py:23 +msgid "User display name" +msgstr "" + +#: tickets/models/comment.py:24 +msgid "Body" +msgstr "" + +#: tickets/models/flow.py:19 tickets/models/flow.py:61 +#: tickets/models/ticket/general.py:42 +msgid "Approve level" +msgstr "" + +#: tickets/models/flow.py:24 tickets/serializers/flow.py:17 +msgid "Approve strategy" +msgstr "" + +#: tickets/models/flow.py:29 tickets/serializers/flow.py:19 +msgid "Assignees" +msgstr "" + +#: tickets/models/flow.py:33 +msgid "Ticket flow approval rule" +msgstr "" + +#: tickets/models/flow.py:66 +msgid "Ticket flow" +msgstr "" + +#: tickets/models/relation.py:12 +msgid "Ticket session relation" +msgstr "" + +#: tickets/models/ticket/apply_application.py:10 +#: tickets/models/ticket/apply_asset.py:13 +msgid "Permission name" +msgstr "" + +#: tickets/models/ticket/apply_application.py:19 +msgid "Apply applications" +msgstr "" + +#: tickets/models/ticket/apply_application.py:22 +msgid "Apply system users" +msgstr "" + +#: tickets/models/ticket/apply_asset.py:9 +#: tickets/serializers/ticket/apply_asset.py:14 +msgid "Select at least one asset or node" +msgstr "" + +#: tickets/models/ticket/apply_asset.py:17 +msgid "Apply accounts" +msgstr "" + +#: tickets/models/ticket/apply_asset.py:26 +msgid "Apply Asset Ticket" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:9 +msgid "Run user" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:11 +msgid "Run asset" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:12 +msgid "Run command" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:19 +msgid "Command filter acl" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:23 +msgid "Apply Command Ticket" +msgstr "" + +#: tickets/models/ticket/general.py:77 +msgid "Ticket step" +msgstr "" + +#: tickets/models/ticket/general.py:95 +msgid "Ticket assignee" +msgstr "" + +#: tickets/models/ticket/general.py:270 +msgid "Title" +msgstr "" + +#: tickets/models/ticket/general.py:290 +msgid "TicketFlow" +msgstr "" + +#: tickets/models/ticket/general.py:293 +msgid "Approval step" +msgstr "" + +#: tickets/models/ticket/general.py:296 +msgid "Relation snapshot" +msgstr "" + +#: tickets/models/ticket/general.py:399 +msgid "Please try again" +msgstr "" + +#: tickets/models/ticket/general.py:475 +msgid "Super ticket" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:11 +msgid "Login user" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:14 +msgid "Login asset" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:17 +msgid "Login account" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:27 +msgid "Apply Login Asset Ticket" +msgstr "" + +#: tickets/models/ticket/login_confirm.py:15 +msgid "Apply Login Ticket" +msgstr "" + +#: tickets/notifications.py:63 +msgid "Ticket basic info" +msgstr "" + +#: tickets/notifications.py:64 +msgid "Ticket applied info" +msgstr "" + +#: tickets/notifications.py:105 +msgid "Your has a new ticket, applicant - {}" +msgstr "" + +#: tickets/notifications.py:109 +msgid "{}: New Ticket - {} ({})" +msgstr "" + +#: tickets/notifications.py:155 +msgid "Your ticket has been processed, processor - {}" +msgstr "" + +#: tickets/notifications.py:159 +msgid "Ticket has processed - {} ({})" +msgstr "" + +#: tickets/serializers/flow.py:20 +msgid "Assignees display" +msgstr "" + +#: tickets/serializers/flow.py:46 +msgid "Please select the Assignees" +msgstr "" + +#: tickets/serializers/flow.py:74 +msgid "The current organization type already exists" +msgstr "" + +#: tickets/serializers/super_ticket.py:15 +msgid "Processor" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:16 +msgid "Support fuzzy search, and display up to 10 items" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:22 +msgid "Apply assets" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:26 +msgid "Apply nodes" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:28 +msgid "Apply actions" +msgstr "" + +#: tickets/serializers/ticket/common.py:15 +#: tickets/serializers/ticket/common.py:75 +msgid "Created by ticket ({}-{})" +msgstr "" + +#: tickets/serializers/ticket/common.py:67 +msgid "The expiration date should be greater than the start date" +msgstr "" + +#: tickets/serializers/ticket/common.py:82 +msgid "Permission named `{}` already exists" +msgstr "" + +#: tickets/serializers/ticket/ticket.py:89 +msgid "The ticket flow `{}` does not exist" +msgstr "" + +#: tickets/templates/tickets/_msg_ticket.html:21 +msgid "View details" +msgstr "" + +#: tickets/templates/tickets/_msg_ticket.html:26 +msgid "Direct approval" +msgstr "" + +#: tickets/templates/tickets/approve_check_password.html:11 +msgid "Ticket information" +msgstr "" + +#: tickets/templates/tickets/approve_check_password.html:28 +#: tickets/views/approve.py:43 tickets/views/approve.py:80 +msgid "Ticket approval" +msgstr "" + +#: tickets/templates/tickets/approve_check_password.html:43 +msgid "Approval" +msgstr "" + +#: tickets/views/approve.py:44 +msgid "" +"This ticket does not exist, the process has ended, or this link has expired" +msgstr "" + +#: tickets/views/approve.py:72 +msgid "Click the button below to approve or reject" +msgstr "" + +#: tickets/views/approve.py:81 +msgid "After successful authentication, this ticket can be approved directly" +msgstr "" + +#: tickets/views/approve.py:105 +msgid "Illegal approval action" +msgstr "" + +#: tickets/views/approve.py:119 +msgid "This user is not authorized to approve this ticket" +msgstr "" + +#: users/api/user.py:155 +msgid "Can not invite self" +msgstr "" + +#: users/api/user.py:208 +msgid "Could not reset self otp, use profile reset instead" +msgstr "" + +#: users/apps.py:9 +msgid "App Users" +msgstr "" + +#: users/const.py:10 +msgid "System administrator" +msgstr "" + +#: users/const.py:11 +msgid "System auditor" +msgstr "" + +#: users/const.py:12 +msgid "Organization administrator" +msgstr "" + +#: users/const.py:13 +msgid "Organization auditor" +msgstr "" + +#: users/const.py:18 +msgid "Reset link will be generated and sent to the user" +msgstr "" + +#: users/const.py:19 +msgid "Set password" +msgstr "" + +#: users/const.py:23 +msgid "AUTO" +msgstr "" + +#: users/const.py:31 +msgid "Full screen" +msgstr "" + +#: users/const.py:32 +msgid "Multi screen" +msgstr "" + +#: users/const.py:33 +msgid "Drives redirect" +msgstr "" + +#: users/const.py:37 +msgid "Current window" +msgstr "" + +#: users/const.py:38 +msgid "New window" +msgstr "" + +#: users/const.py:47 +msgid "High(32 bit)" +msgstr "" + +#: users/const.py:48 +msgid "Medium(16 bit)" +msgstr "" + +#: users/const.py:69 +msgid "Replace" +msgstr "" + +#: users/const.py:70 +msgid "Suffix" +msgstr "" + +#: users/exceptions.py:10 +msgid "MFA not enabled" +msgstr "" + +#: users/exceptions.py:20 +msgid "Unable to delete all users" +msgstr "" + +#: users/forms/profile.py:48 +msgid "" +"When enabled, you will enter the MFA binding process the next time you log " +"in. you can also directly bind in \"personal information -> quick " +"modification -> change MFA Settings\"!" +msgstr "" + +#: users/forms/profile.py:59 +msgid "* Enable MFA to make the account more secure." +msgstr "" + +#: users/forms/profile.py:68 +msgid "" +"In order to protect you and your company, please keep your account, password " +"and key sensitive information properly. (for example: setting complex " +"password, enabling MFA)" +msgstr "" + +#: users/forms/profile.py:75 +msgid "Finish" +msgstr "" + +#: users/forms/profile.py:82 +msgid "New password" +msgstr "" + +#: users/forms/profile.py:87 +msgid "Confirm password" +msgstr "" + +#: users/forms/profile.py:95 +msgid "Password does not match" +msgstr "" + +#: users/forms/profile.py:104 +msgid "The phone number must contain an area code, for example, +86" +msgstr "" + +#: users/forms/profile.py:120 +msgid "Old password" +msgstr "" + +#: users/forms/profile.py:130 +msgid "Old password error" +msgstr "" + +#: users/forms/profile.py:140 +msgid "Automatically configure and download the SSH key" +msgstr "" + +#: users/forms/profile.py:142 +msgid "ssh public key" +msgstr "" + +#: users/forms/profile.py:143 +msgid "ssh-rsa AAAA..." +msgstr "" + +#: users/forms/profile.py:144 +msgid "Paste your id_rsa.pub here." +msgstr "" + +#: users/forms/profile.py:157 +msgid "Public key should not be the same as your old one." +msgstr "" + +#: users/forms/profile.py:161 users/serializers/profile.py:76 +#: users/serializers/profile.py:165 users/serializers/profile.py:192 +msgid "Not a valid ssh public key" +msgstr "" + +#: users/forms/profile.py:172 users/models/user.py:907 +#: xpack/plugins/cloud/serializers/account_attrs.py:210 +msgid "Public key" +msgstr "" + +#: users/models/preference.py:38 users/serializers/preference/preference.py:19 +msgid "Preference" +msgstr "" + +#: users/models/user.py:656 users/serializers/profile.py:94 +msgid "Force enable" +msgstr "" + +#: users/models/user.py:761 +msgid "Lark" +msgstr "" + +#: users/models/user.py:886 users/serializers/user.py:182 +msgid "Is service account" +msgstr "" + +#: users/models/user.py:888 +msgid "Avatar" +msgstr "" + +#: users/models/user.py:891 +msgid "Wechat" +msgstr "" + +#: users/models/user.py:894 users/serializers/user.py:112 +msgid "Phone" +msgstr "" + +#: users/models/user.py:900 +msgid "OTP secret key" +msgstr "" + +#: users/models/user.py:912 users/serializers/profile.py:129 +#: users/serializers/user.py:179 +msgid "Is first login" +msgstr "" + +#: users/models/user.py:921 +msgid "Date password last updated" +msgstr "" + +#: users/models/user.py:924 +msgid "Need update password" +msgstr "" + +#: users/models/user.py:935 +msgid "Date api key used" +msgstr "" + +#: users/models/user.py:1057 +msgid "Can not delete admin user" +msgstr "" + +#: users/models/user.py:1071 +msgid "Can invite user" +msgstr "" + +#: users/models/user.py:1072 +msgid "Can remove user" +msgstr "" + +#: users/models/user.py:1073 +msgid "Can match user" +msgstr "" + +#: users/models/user.py:1082 +msgid "Administrator" +msgstr "" + +#: users/models/user.py:1085 +msgid "Administrator is the super user of system" +msgstr "" + +#: users/models/user.py:1110 +msgid "User password history" +msgstr "" + +#: users/notifications.py:55 +#: users/templates/users/_msg_password_expire_reminder.html:17 +#: users/templates/users/reset_password.html:5 +#: users/templates/users/reset_password.html:6 +msgid "Reset password" +msgstr "" + +#: users/notifications.py:85 users/views/profile/reset.py:233 +msgid "Reset password success" +msgstr "" + +#: users/notifications.py:117 +msgid "Reset public key success" +msgstr "" + +#: users/notifications.py:143 +msgid "Password is about expire" +msgstr "" + +#: users/notifications.py:171 +msgid "Account is about expire" +msgstr "" + +#: users/notifications.py:193 +msgid "Reset SSH Key" +msgstr "" + +#: users/notifications.py:214 +msgid "Reset MFA" +msgstr "" + +#: users/serializers/preference/koko.py:10 +msgid "File name conflict resolution" +msgstr "" + +#: users/serializers/preference/koko.py:14 +msgid "Terminal theme name" +msgstr "" + +#: users/serializers/preference/lina.py:13 +msgid "New file encryption password" +msgstr "" + +#: users/serializers/preference/lina.py:18 +msgid "Confirm file encryption password" +msgstr "" + +#: users/serializers/preference/lina.py:31 users/serializers/profile.py:48 +msgid "The newly set password is inconsistent" +msgstr "" + +#: users/serializers/preference/luna.py:26 +msgid "Async loading of asset tree" +msgstr "" + +#: users/serializers/preference/luna.py:30 +msgid "Connect default open method" +msgstr "" + +#: users/serializers/preference/luna.py:37 +msgid "RDP resolution" +msgstr "" + +#: users/serializers/preference/luna.py:41 +msgid "Keyboard layout" +msgstr "" + +#: users/serializers/preference/luna.py:45 +msgid "RDP client option" +msgstr "" + +#: users/serializers/preference/luna.py:49 +msgid "RDP color quality" +msgstr "" + +#: users/serializers/preference/luna.py:53 +msgid "RDP smart size" +msgstr "" + +#: users/serializers/preference/luna.py:54 +msgid "" +"Determines whether the client computer should scale the content on the " +"remote computer to fit the window size of the client computer when the " +"window is resized." +msgstr "" + +#: users/serializers/preference/luna.py:59 +msgid "Remote application connection method" +msgstr "" + +#: users/serializers/preference/luna.py:66 +msgid "Character terminal font size" +msgstr "" + +#: users/serializers/preference/luna.py:69 +msgid "Backspace as Ctrl+H" +msgstr "" + +#: users/serializers/preference/luna.py:72 +msgid "Right click quickly paste" +msgstr "" + +#: users/serializers/preference/luna.py:78 +msgid "Graphics" +msgstr "" + +#: users/serializers/preference/luna.py:79 +msgid "Command line" +msgstr "" + +#: users/serializers/profile.py:29 +msgid "The old password is incorrect" +msgstr "" + +#: users/serializers/profile.py:36 users/serializers/profile.py:179 +msgid "Password does not match security rules" +msgstr "" + +#: users/serializers/profile.py:40 +msgid "The new password cannot be the last {} passwords" +msgstr "" + +#: users/serializers/user.py:45 +msgid "System roles" +msgstr "" + +#: users/serializers/user.py:49 +msgid "Org roles" +msgstr "" + +#: users/serializers/user.py:52 +msgid "Organizations and roles" +msgstr "" + +#: users/serializers/user.py:94 +msgid "Password setting" +msgstr "" + +#: users/serializers/user.py:96 +msgid "MFA enabled" +msgstr "" + +#: users/serializers/user.py:98 +msgid "MFA force enabled" +msgstr "" + +#: users/serializers/user.py:100 +msgid "Login blocked" +msgstr "" + +#: users/serializers/user.py:103 users/serializers/user.py:188 +msgid "Is OTP bound" +msgstr "" + +#: users/serializers/user.py:104 +msgid "Super Administrator" +msgstr "" + +#: users/serializers/user.py:105 +msgid "Organization Administrator" +msgstr "" + +#: users/serializers/user.py:107 +msgid "Can public key authentication" +msgstr "" + +#: users/serializers/user.py:176 +msgid "Superuser" +msgstr "" + +#: users/serializers/user.py:183 +msgid "Is org admin" +msgstr "" + +#: users/serializers/user.py:185 +msgid "Avatar url" +msgstr "" + +#: users/serializers/user.py:189 +msgid "MFA level" +msgstr "" + +#: users/serializers/user.py:312 +msgid "" +"For security, only a partial of users is displayed. You can search for more" +msgstr "" + +#: users/serializers/user.py:345 +msgid "name not unique" +msgstr "" + +#: users/signal_handlers.py:35 +msgid "" +"The administrator has enabled \"Only allow existing users to log in\", \n" +" and the current user is not in the user list. Please contact the " +"administrator." +msgstr "" + +#: users/signal_handlers.py:169 +msgid "Clean up expired user sessions" +msgstr "" + +#: users/tasks.py:25 +msgid "Check password expired" +msgstr "" + +#: users/tasks.py:39 +msgid "Periodic check password expired" +msgstr "" + +#: users/tasks.py:53 +msgid "Check user expired" +msgstr "" + +#: users/tasks.py:70 +msgid "Periodic check user expired" +msgstr "" + +#: users/tasks.py:84 +msgid "Check unused users" +msgstr "" + +#: users/tasks.py:123 +msgid "The user has not logged in recently and has been disabled." +msgstr "" + +#: users/templates/users/_msg_account_expire_reminder.html:7 +msgid "Your account will expire in" +msgstr "" + +#: users/templates/users/_msg_account_expire_reminder.html:8 +msgid "" +"In order not to affect your normal work, please contact the administrator " +"for confirmation." +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:7 +msgid "Your password will expire in" +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:8 +msgid "" +"For your account security, please click on the link below to update your " +"password in time" +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:11 +msgid "Click here update password" +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:16 +msgid "If your password has expired, please click the link below to" +msgstr "" + +#: users/templates/users/_msg_reset_mfa.html:7 +msgid "Your MFA has been reset by site administrator" +msgstr "" + +#: users/templates/users/_msg_reset_mfa.html:8 +#: users/templates/users/_msg_reset_ssh_key.html:8 +msgid "Please click the link below to set" +msgstr "" + +#: users/templates/users/_msg_reset_mfa.html:11 +#: users/templates/users/_msg_reset_ssh_key.html:11 +msgid "Click here set" +msgstr "" + +#: users/templates/users/_msg_reset_ssh_key.html:7 +msgid "Your ssh public key has been reset by site administrator" +msgstr "" + +#: users/templates/users/_msg_user_created.html:15 +msgid "click here to set your password" +msgstr "" + +#: users/templates/users/forgot_password.html:46 +msgid "Input your email account, that will send a email to your" +msgstr "" + +#: users/templates/users/forgot_password.html:49 +msgid "" +"Enter your mobile number and a verification code will be sent to your phone" +msgstr "" + +#: users/templates/users/forgot_password.html:71 +msgid "Email account" +msgstr "" + +#: users/templates/users/forgot_password.html:93 +msgid "Mobile number" +msgstr "" + +#: users/templates/users/forgot_password.html:101 +msgid "Send" +msgstr "" + +#: users/templates/users/forgot_password.html:105 +#: users/templates/users/forgot_password_previewing.html:30 +msgid "Submit" +msgstr "" + +#: users/templates/users/forgot_password_previewing.html:21 +msgid "Please enter the username for which you want to retrieve the password" +msgstr "" + +#: users/templates/users/mfa_setting.html:24 +msgid "Enable MFA" +msgstr "" + +#: users/templates/users/mfa_setting.html:30 +msgid "MFA force enable, cannot disable" +msgstr "" + +#: users/templates/users/mfa_setting.html:48 +msgid "MFA setting" +msgstr "" + +#: users/templates/users/mfa_setting.html:61 +msgid "Reset" +msgstr "" + +#: users/templates/users/reset_password.html:23 +msgid "Your password must satisfy" +msgstr "" + +#: users/templates/users/reset_password.html:24 +msgid "Password strength" +msgstr "" + +#: users/templates/users/reset_password.html:48 +msgid "Very weak" +msgstr "" + +#: users/templates/users/reset_password.html:49 +msgid "Weak" +msgstr "" + +#: users/templates/users/reset_password.html:51 +msgid "Medium" +msgstr "" + +#: users/templates/users/reset_password.html:52 +msgid "Strong" +msgstr "" + +#: users/templates/users/reset_password.html:53 +msgid "Very strong" +msgstr "" + +#: users/templates/users/user_otp_check_password.html:6 +msgid "Enable OTP" +msgstr "" + +#: users/templates/users/user_otp_enable_bind.html:6 +msgid "Bind one-time password authenticator" +msgstr "" + +#: users/templates/users/user_otp_enable_bind.html:13 +msgid "" +"Use the MFA Authenticator application to scan the following qr code for a 6-" +"bit verification code" +msgstr "" + +#: users/templates/users/user_otp_enable_bind.html:22 +#: users/templates/users/user_verify_mfa.html:27 +msgid "Six figures" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:6 +msgid "Install app" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:13 +msgid "" +"Download and install the MFA Authenticator application on your phone or " +"applet of WeChat" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:18 +msgid "Android downloads" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:23 +msgid "iPhone downloads" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:27 +msgid "" +"After installation, click the next step to enter the binding page (if " +"installed, go to the next step directly)." +msgstr "" + +#: users/templates/users/user_password_verify.html:8 +#: users/templates/users/user_password_verify.html:9 +msgid "Verify password" +msgstr "" + +#: users/templates/users/user_verify_mfa.html:9 +msgid "Authenticate" +msgstr "" + +#: users/templates/users/user_verify_mfa.html:15 +msgid "" +"The account protection has been opened, please complete the following " +"operations according to the prompts" +msgstr "" + +#: users/templates/users/user_verify_mfa.html:17 +msgid "Open MFA Authenticator and enter the 6-bit dynamic code" +msgstr "" + +#: users/views/profile/otp.py:106 +msgid "Already bound" +msgstr "" + +#: users/views/profile/otp.py:107 +msgid "MFA already bound, disable first, then bound" +msgstr "" + +#: users/views/profile/otp.py:134 +msgid "OTP enable success" +msgstr "" + +#: users/views/profile/otp.py:135 +msgid "OTP enable success, return login page" +msgstr "" + +#: users/views/profile/otp.py:177 +msgid "Disable OTP" +msgstr "" + +#: users/views/profile/otp.py:183 +msgid "OTP disable success" +msgstr "" + +#: users/views/profile/otp.py:184 +msgid "OTP disable success, return login page" +msgstr "" + +#: users/views/profile/password.py:33 users/views/profile/password.py:38 +msgid "Password invalid" +msgstr "" + +#: users/views/profile/reset.py:66 +msgid "" +"Non-local users can log in only from third-party platforms and cannot change " +"their passwords: {}" +msgstr "" + +#: users/views/profile/reset.py:188 users/views/profile/reset.py:199 +msgid "Token invalid or expired" +msgstr "" + +#: users/views/profile/reset.py:204 +msgid "User auth from {}, go there change password" +msgstr "" + +#: users/views/profile/reset.py:211 +msgid "* Your password does not meet the requirements" +msgstr "" + +#: users/views/profile/reset.py:217 +msgid "* The new password cannot be the last {} passwords" +msgstr "" + +#: users/views/profile/reset.py:234 +msgid "Reset password success, return to login page" +msgstr "" + +#: xpack/apps.py:8 +msgid "XPACK" +msgstr "" + +#: xpack/exceptions.py:7 +msgid "" +"The current task is not synchronized with unmatched policy assets, skipping" +msgstr "" + +#: xpack/plugins/cloud/api.py:56 +msgid "Test connection successful" +msgstr "" + +#: xpack/plugins/cloud/api.py:58 +msgid "Test connection failed: {}" +msgstr "" + +#: xpack/plugins/cloud/const.py:8 +msgid "Alibaba Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:9 +msgid "AWS (International)" +msgstr "" + +#: xpack/plugins/cloud/const.py:10 +msgid "AWS (China)" +msgstr "" + +#: xpack/plugins/cloud/const.py:11 +msgid "Azure (China)" +msgstr "" + +#: xpack/plugins/cloud/const.py:12 +msgid "Azure (International)" +msgstr "" + +#: xpack/plugins/cloud/const.py:14 +msgid "Baidu Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:15 +msgid "JD Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:16 +msgid "KingSoft Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:17 +msgid "Tencent Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:18 +msgid "Tencent Cloud (Lighthouse)" +msgstr "" + +#: xpack/plugins/cloud/const.py:19 +msgid "Google Cloud Platform" +msgstr "" + +#: xpack/plugins/cloud/const.py:20 +msgid "UCloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:22 +msgid "VMware" +msgstr "" + +#: xpack/plugins/cloud/const.py:23 xpack/plugins/cloud/providers/nutanix.py:15 +msgid "Nutanix" +msgstr "" + +#: xpack/plugins/cloud/const.py:24 +msgid "Huawei Private Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:25 +msgid "Qingyun Private Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:26 +msgid "CTYun Private Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:27 +msgid "OpenStack" +msgstr "" + +#: xpack/plugins/cloud/const.py:28 xpack/plugins/cloud/providers/zstack.py:21 +msgid "ZStack" +msgstr "" + +#: xpack/plugins/cloud/const.py:29 +msgid "Fusion Compute" +msgstr "" + +#: xpack/plugins/cloud/const.py:30 +msgid "SCP" +msgstr "" + +#: xpack/plugins/cloud/const.py:31 +msgid "Apsara Stack" +msgstr "" + +#: xpack/plugins/cloud/const.py:36 +msgid "Private IP" +msgstr "" + +#: xpack/plugins/cloud/const.py:37 +msgid "Public IP" +msgstr "" + +#: xpack/plugins/cloud/const.py:41 xpack/plugins/cloud/models.py:303 +msgid "Instance name" +msgstr "" + +#: xpack/plugins/cloud/const.py:42 +msgid "Instance name and Partial IP" +msgstr "" + +#: xpack/plugins/cloud/const.py:47 +msgid "Succeed" +msgstr "" + +#: xpack/plugins/cloud/const.py:51 +msgid "Unsync" +msgstr "" + +#: xpack/plugins/cloud/const.py:52 +msgid "New Sync" +msgstr "" + +#: xpack/plugins/cloud/const.py:53 +msgid "Synced" +msgstr "" + +#: xpack/plugins/cloud/const.py:54 +msgid "Released" +msgstr "" + +#: xpack/plugins/cloud/const.py:58 +msgid "And" +msgstr "" + +#: xpack/plugins/cloud/const.py:59 +msgid "Or" +msgstr "" + +#: xpack/plugins/cloud/manager.py:56 +msgid "Account unavailable" +msgstr "" + +#: xpack/plugins/cloud/meta.py:9 +msgid "Cloud center" +msgstr "" + +#: xpack/plugins/cloud/models.py:34 +msgid "Provider" +msgstr "" + +#: xpack/plugins/cloud/models.py:37 +#: xpack/plugins/cloud/serializers/account.py:67 +msgid "Attrs" +msgstr "" + +#: xpack/plugins/cloud/models.py:38 +msgid "Validity" +msgstr "" + +#: xpack/plugins/cloud/models.py:43 +msgid "Cloud account" +msgstr "" + +#: xpack/plugins/cloud/models.py:45 +msgid "Test cloud account" +msgstr "" + +#: xpack/plugins/cloud/models.py:92 xpack/plugins/cloud/serializers/task.py:159 +msgid "Regions" +msgstr "" + +#: xpack/plugins/cloud/models.py:95 +msgid "Hostname strategy" +msgstr "" + +#: xpack/plugins/cloud/models.py:100 +#: xpack/plugins/cloud/serializers/task.py:162 +msgid "IP network segment group" +msgstr "" + +#: xpack/plugins/cloud/models.py:103 +#: xpack/plugins/cloud/serializers/task.py:167 +msgid "Sync IP type" +msgstr "" + +#: xpack/plugins/cloud/models.py:106 +#: xpack/plugins/cloud/serializers/task.py:185 +msgid "Always update" +msgstr "" + +#: xpack/plugins/cloud/models.py:108 +msgid "Fully synchronous" +msgstr "" + +#: xpack/plugins/cloud/models.py:113 +msgid "Date last sync" +msgstr "" + +#: xpack/plugins/cloud/models.py:116 xpack/plugins/cloud/models.py:321 +#: xpack/plugins/cloud/models.py:345 +msgid "Strategy" +msgstr "" + +#: xpack/plugins/cloud/models.py:121 xpack/plugins/cloud/models.py:200 +msgid "Sync instance task" +msgstr "" + +#: xpack/plugins/cloud/models.py:211 xpack/plugins/cloud/models.py:263 +msgid "Date sync" +msgstr "" + +#: xpack/plugins/cloud/models.py:215 +msgid "Sync instance snapshot" +msgstr "" + +#: xpack/plugins/cloud/models.py:219 +msgid "Sync instance task execution" +msgstr "" + +#: xpack/plugins/cloud/models.py:243 +msgid "Sync task" +msgstr "" + +#: xpack/plugins/cloud/models.py:247 +msgid "Sync instance task history" +msgstr "" + +#: xpack/plugins/cloud/models.py:250 +msgid "Instance" +msgstr "" + +#: xpack/plugins/cloud/models.py:267 +msgid "Sync instance detail" +msgstr "" + +#: xpack/plugins/cloud/models.py:279 xpack/plugins/cloud/serializers/task.py:72 +msgid "Rule relation" +msgstr "" + +#: xpack/plugins/cloud/models.py:288 +msgid "Task strategy" +msgstr "" + +#: xpack/plugins/cloud/models.py:292 +msgid "Equal" +msgstr "" + +#: xpack/plugins/cloud/models.py:293 +msgid "Not Equal" +msgstr "" + +#: xpack/plugins/cloud/models.py:294 +msgid "In" +msgstr "" + +#: xpack/plugins/cloud/models.py:295 +msgid "Contains" +msgstr "" + +#: xpack/plugins/cloud/models.py:296 +msgid "Exclude" +msgstr "" + +#: xpack/plugins/cloud/models.py:297 +msgid "Startswith" +msgstr "" + +#: xpack/plugins/cloud/models.py:298 +msgid "Endswith" +msgstr "" + +#: xpack/plugins/cloud/models.py:304 +msgid "Instance platform" +msgstr "" + +#: xpack/plugins/cloud/models.py:305 +msgid "Instance address" +msgstr "" + +#: xpack/plugins/cloud/models.py:312 +msgid "Rule attr" +msgstr "" + +#: xpack/plugins/cloud/models.py:316 +msgid "Rule match" +msgstr "" + +#: xpack/plugins/cloud/models.py:318 +msgid "Rule value" +msgstr "" + +#: xpack/plugins/cloud/models.py:325 xpack/plugins/cloud/serializers/task.py:75 +msgid "Strategy rule" +msgstr "" + +#: xpack/plugins/cloud/models.py:340 +msgid "Action attr" +msgstr "" + +#: xpack/plugins/cloud/models.py:342 +msgid "Action value" +msgstr "" + +#: xpack/plugins/cloud/models.py:349 xpack/plugins/cloud/serializers/task.py:78 +msgid "Strategy action" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:18 +msgid "China (Beijing)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:19 +msgid "China (Ningxia)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:22 +msgid "US East (Ohio)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:23 +msgid "US East (N. Virginia)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:24 +msgid "US West (N. California)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:25 +msgid "US West (Oregon)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:26 +msgid "Africa (Cape Town)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:27 +msgid "Asia Pacific (Hong Kong)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:28 +msgid "Asia Pacific (Mumbai)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:29 +msgid "Asia Pacific (Osaka-Local)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:30 +msgid "Asia Pacific (Seoul)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:31 +msgid "Asia Pacific (Singapore)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:32 +msgid "Asia Pacific (Sydney)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:33 +msgid "Asia Pacific (Tokyo)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:34 +msgid "Canada (Central)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:35 +msgid "Europe (Frankfurt)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:36 +msgid "Europe (Ireland)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:37 +msgid "Europe (London)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:38 +msgid "Europe (Milan)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:39 +msgid "Europe (Paris)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:40 +msgid "Europe (Stockholm)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:41 +msgid "Middle East (Bahrain)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:42 +msgid "South America (São Paulo)" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:54 +#: xpack/plugins/cloud/providers/jdcloud.py:125 +msgid "CN North-Beijing" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:55 +#: xpack/plugins/cloud/providers/huaweicloud.py:42 +#: xpack/plugins/cloud/providers/jdcloud.py:128 +msgid "CN South-Guangzhou" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:56 +msgid "CN East-Suzhou" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:57 +#: xpack/plugins/cloud/providers/huaweicloud.py:49 +msgid "CN-Hong Kong" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:58 +msgid "CN Center-Wuhan" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:59 +msgid "CN North-Baoding" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:60 +#: xpack/plugins/cloud/providers/jdcloud.py:127 +msgid "CN East-Shanghai" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:61 +#: xpack/plugins/cloud/providers/huaweicloud.py:51 +msgid "AP-Singapore" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:39 +msgid "CN North-Beijing1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:40 +msgid "CN North-Beijing4" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:41 +msgid "CN North-Ulanqab1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:43 +msgid "CN South-Shenzhen" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:44 +msgid "CN South-Guangzhou-InvitationOnly" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:45 +msgid "CN East-Shanghai2" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:46 +msgid "CN East-Shanghai1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:48 +msgid "CN Southwest-Guiyang1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:50 +msgid "AP-Bangkok" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:53 +msgid "AF-Johannesburg" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:54 +msgid "LA-Mexico City1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:55 +msgid "LA-Santiago" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:56 +msgid "LA-Sao Paulo1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:58 +msgid "TR-Istanbul" +msgstr "" + +#: xpack/plugins/cloud/providers/jdcloud.py:126 +msgid "CN East-Suqian" +msgstr "" + +#: xpack/plugins/cloud/serializers/account.py:68 +msgid "Validity display" +msgstr "" + +#: xpack/plugins/cloud/serializers/account.py:69 +msgid "Provider display" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:17 +msgid "Access key id" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:35 +msgid "Client ID" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:41 +msgid "Tenant ID" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:44 +msgid "Subscription ID" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:98 +#: xpack/plugins/cloud/serializers/account_attrs.py:102 +#: xpack/plugins/cloud/serializers/account_attrs.py:126 +#: xpack/plugins/cloud/serializers/account_attrs.py:156 +#: xpack/plugins/cloud/serializers/account_attrs.py:206 +msgid "API Endpoint" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:108 +msgid "Auth url" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:109 +msgid "eg: http://openstack.example.com:5000/v3" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:112 +msgid "User domain" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:127 +msgid "Cert File" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:128 +msgid "Key File" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:144 +msgid "Service account key" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:145 +msgid "The file is in JSON format" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:163 +msgid "IP address invalid `{}`, {}" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:179 +msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:182 +msgid "" +"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 " +"synchronized.
If the port is 0, all IP addresses are valid." +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:190 +msgid "Hostname prefix" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:193 +msgid "IP segment" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:197 +msgid "Test port" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:200 +msgid "Test timeout" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:216 +msgid "Project" +msgstr "" + +#: xpack/plugins/cloud/serializers/task.py:151 +msgid "" +"Only instances matching the IP range will be synced.
If the instance " +"contains multiple IP addresses, the first IP address that matches will be " +"used as the IP for the created asset.
The default value of * means sync " +"all instances and randomly match IP addresses.
Such as: 192.168.1.0/24, " +"10.1.1.1-10.1.1.20" +msgstr "" + +#: xpack/plugins/cloud/serializers/task.py:157 +msgid "History count" +msgstr "" + +#: xpack/plugins/cloud/serializers/task.py:158 +msgid "Instance count" +msgstr "" + +#: xpack/plugins/cloud/tasks.py:27 +msgid "Run sync instance task" +msgstr "" + +#: xpack/plugins/cloud/tasks.py:41 +msgid "Period clean sync instance task execution" +msgstr "" + +#: xpack/plugins/interface/api.py:52 +msgid "Restore default successfully." +msgstr "" + +#: xpack/plugins/interface/meta.py:9 +msgid "Interface settings" +msgstr "" + +#: xpack/plugins/interface/models.py:23 +msgid "Login title" +msgstr "" + +#: xpack/plugins/interface/models.py:27 +msgid "Login image" +msgstr "" + +#: xpack/plugins/interface/models.py:31 +msgid "Website icon" +msgstr "" + +#: xpack/plugins/interface/models.py:35 +msgid "Index logo" +msgstr "" + +#: xpack/plugins/interface/models.py:39 +msgid "Logout logo" +msgstr "" + +#: xpack/plugins/interface/models.py:41 +#: xpack/plugins/interface/serializers/interface.py:26 +msgid "Theme" +msgstr "" + +#: xpack/plugins/interface/models.py:42 +msgid "Beian link" +msgstr "" + +#: xpack/plugins/interface/models.py:43 +msgid "Beian text" +msgstr "" + +#: xpack/plugins/interface/models.py:46 xpack/plugins/interface/models.py:87 +msgid "Interface setting" +msgstr "" + +#: xpack/plugins/interface/serializers/interface.py:37 +msgid "Wide logo on top" +msgstr "" + +#: xpack/plugins/interface/serializers/interface.py:38 +msgid "Small logo without text" +msgstr "" + +#: xpack/plugins/license/api.py:52 +msgid "License import successfully" +msgstr "" + +#: xpack/plugins/license/api.py:53 +msgid "License is invalid" +msgstr "" + +#: xpack/plugins/license/meta.py:10 xpack/plugins/license/models.py:144 +msgid "License" +msgstr "" + +#: xpack/plugins/license/models.py:80 +msgid "Basic edition" +msgstr "" + +#: xpack/plugins/license/models.py:82 +msgid "Standard edition" +msgstr "" + +#: xpack/plugins/license/models.py:84 +msgid "Professional edition" +msgstr "" + +#: xpack/plugins/license/models.py:86 +msgid "Ultimate edition" +msgstr "" diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo new file mode 100644 index 000000000..315c546b7 --- /dev/null +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5cc8f923c01a87b106a54f8a7c53abdb98683b1c4b4f975f9a3ae8af5fae73c8 +size 373 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po new file mode 100644 index 000000000..54fe20fd9 --- /dev/null +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -0,0 +1,9037 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-05-10 19:19+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: accounts/api/automations/base.py:79 tickets/api/ticket.py:132 +msgid "The parameter 'action' must be [{}]" +msgstr "" + +#: accounts/automations/change_secret/manager.py:225 +#, python-format +msgid "Success: %s, Failed: %s, Total: %s" +msgstr "" + +#: accounts/const/account.py:6 +#: accounts/serializers/automations/change_secret.py:34 +#: audits/signal_handlers/login_log.py:34 authentication/confirm/password.py:9 +#: authentication/confirm/password.py:24 authentication/confirm/password.py:26 +#: authentication/forms.py:28 +#: authentication/templates/authentication/login.html:329 +#: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 +#: settings/serializers/msg.py:35 terminal/serializers/storage.py:123 +#: terminal/serializers/storage.py:142 users/forms/profile.py:21 +#: users/serializers/user.py:110 +#: users/templates/users/_msg_user_created.html:13 +#: users/templates/users/user_password_verify.html:18 +#: xpack/plugins/cloud/serializers/account_attrs.py:28 +msgid "Password" +msgstr "" + +#: accounts/const/account.py:7 +#: accounts/serializers/automations/change_secret.py:35 +#: terminal/serializers/storage.py:124 +msgid "SSH key" +msgstr "" + +#: accounts/const/account.py:8 authentication/models/access_key.py:42 +msgid "Access key" +msgstr "" + +#: accounts/const/account.py:9 authentication/backends/passkey/models.py:16 +#: authentication/models/sso_token.py:14 settings/serializers/feature.py:52 +msgid "Token" +msgstr "" + +#: accounts/const/account.py:10 +msgid "API key" +msgstr "" + +#: accounts/const/account.py:14 common/db/fields.py:235 +#: settings/serializers/terminal.py:14 +msgid "All" +msgstr "" + +#: accounts/const/account.py:15 accounts/models/virtual.py:26 +msgid "Manual input" +msgstr "" + +#: accounts/const/account.py:16 +msgid "Dynamic user" +msgstr "" + +#: accounts/const/account.py:17 +msgid "Anonymous account" +msgstr "" + +#: accounts/const/account.py:18 +msgid "Specified account" +msgstr "" + +#: accounts/const/account.py:26 users/models/user.py:751 +msgid "Local" +msgstr "" + +#: accounts/const/account.py:27 +msgid "Collected" +msgstr "" + +#: accounts/const/account.py:28 accounts/serializers/account/account.py:28 +#: settings/serializers/auth/sms.py:79 +msgid "Template" +msgstr "" + +#: accounts/const/account.py:32 ops/const.py:46 +msgid "Skip" +msgstr "" + +#: accounts/const/account.py:33 audits/const.py:24 rbac/tree.py:239 +#: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 +msgid "Update" +msgstr "" + +#: accounts/const/account.py:34 accounts/const/automation.py:109 +#: accounts/serializers/automations/change_secret.py:164 audits/const.py:62 +#: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 +#: ops/const.py:76 terminal/const.py:79 xpack/plugins/cloud/const.py:46 +msgid "Failed" +msgstr "" + +#: accounts/const/automation.py:24 rbac/tree.py:52 +msgid "Push account" +msgstr "" + +#: accounts/const/automation.py:25 +msgid "Change secret" +msgstr "" + +#: accounts/const/automation.py:26 +msgid "Verify account" +msgstr "" + +#: accounts/const/automation.py:27 accounts/tasks/remove_account.py:24 +#: accounts/tasks/remove_account.py:33 +msgid "Remove account" +msgstr "" + +#: accounts/const/automation.py:28 +msgid "Gather accounts" +msgstr "" + +#: accounts/const/automation.py:29 +msgid "Verify gateway account" +msgstr "" + +#: accounts/const/automation.py:47 +msgid "Specific secret" +msgstr "" + +#: accounts/const/automation.py:48 +msgid "Random generate" +msgstr "" + +#: accounts/const/automation.py:52 ops/const.py:13 +msgid "Append SSH KEY" +msgstr "" + +#: accounts/const/automation.py:53 ops/const.py:14 +msgid "Empty and append SSH KEY" +msgstr "" + +#: accounts/const/automation.py:54 ops/const.py:15 +msgid "Replace (Replace only keys pushed by JumpServer) " +msgstr "" + +#: accounts/const/automation.py:59 +msgid "On asset create" +msgstr "" + +#: accounts/const/automation.py:62 +msgid "On perm add user" +msgstr "" + +#: accounts/const/automation.py:64 +msgid "On perm add user group" +msgstr "" + +#: accounts/const/automation.py:66 +msgid "On perm add asset" +msgstr "" + +#: accounts/const/automation.py:68 +msgid "On perm add node" +msgstr "" + +#: accounts/const/automation.py:70 +msgid "On perm add account" +msgstr "" + +#: accounts/const/automation.py:72 +msgid "On asset join node" +msgstr "" + +#: accounts/const/automation.py:74 +msgid "On user join group" +msgstr "" + +#: accounts/const/automation.py:82 +msgid "On perm change" +msgstr "" + +#: accounts/const/automation.py:89 +msgid "Inherit from group or node" +msgstr "" + +#: accounts/const/automation.py:97 +msgid "Create and push" +msgstr "" + +#: accounts/const/automation.py:98 +msgid "Only create" +msgstr "" + +#: accounts/const/automation.py:103 +#: authentication/serializers/password_mfa.py:16 +#: authentication/serializers/password_mfa.py:24 +#: notifications/backends/__init__.py:10 settings/serializers/msg.py:22 +#: settings/serializers/msg.py:64 users/forms/profile.py:100 +#: users/forms/profile.py:108 users/models/user.py:876 +#: users/templates/users/forgot_password.html:162 +#: users/views/profile/reset.py:94 +msgid "Email" +msgstr "" + +#: accounts/const/automation.py:105 terminal/const.py:87 +msgid "SFTP" +msgstr "" + +#: accounts/const/automation.py:110 +#: accounts/serializers/automations/change_secret.py:163 audits/const.py:61 +#: audits/models.py:64 audits/signal_handlers/activity_log.py:33 +#: common/const/choices.py:18 ops/const.py:74 ops/serializers/celery.py:48 +#: terminal/const.py:78 terminal/models/session/sharing.py:121 +#: tickets/views/approve.py:128 +msgid "Success" +msgstr "" + +#: accounts/const/automation.py:111 common/const/choices.py:16 +#: terminal/const.py:77 tickets/const.py:29 tickets/const.py:38 +msgid "Pending" +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 settings/serializers/feature.py:43 +msgid "HCP Vault" +msgstr "" + +#: accounts/mixins.py:35 +msgid "Export all" +msgstr "" + +#: accounts/mixins.py:37 +msgid "Export only selected items" +msgstr "" + +#: accounts/mixins.py:42 +#, python-format +msgid "Export filtered: %s" +msgstr "" + +#: accounts/mixins.py:48 +#, python-format +msgid "User %s view/export secret" +msgstr "" + +#: accounts/models/account.py:49 +#: accounts/models/automations/gather_account.py:16 +#: accounts/serializers/account/account.py:215 +#: accounts/serializers/account/account.py:260 +#: accounts/serializers/account/gathered_account.py:10 +#: accounts/serializers/automations/change_secret.py:108 +#: accounts/serializers/automations/change_secret.py:140 +#: accounts/templates/accounts/asset_account_change_info.html:7 +#: accounts/templates/accounts/change_secret_failed_info.html:11 +#: acls/serializers/base.py:123 assets/models/asset/common.py:95 +#: assets/models/asset/common.py:349 assets/models/cmd_filter.py:36 +#: audits/models.py:58 authentication/models/connection_token.py:36 +#: perms/models/asset_permission.py:69 terminal/backends/command/models.py:17 +#: terminal/models/session/session.py:32 terminal/notifications.py:155 +#: terminal/serializers/command.py:17 terminal/serializers/session.py:28 +#: terminal/templates/terminal/_msg_command_warning.html:4 +#: terminal/templates/terminal/_msg_session_sharing.html:4 +#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:256 +msgid "Asset" +msgstr "" + +#: accounts/models/account.py:53 accounts/models/template.py:16 +#: accounts/serializers/account/account.py:222 +#: accounts/serializers/account/account.py:270 +#: accounts/serializers/account/template.py:27 +#: authentication/serializers/connect_token_secret.py:50 +msgid "Su from" +msgstr "" + +#: accounts/models/account.py:55 assets/const/protocol.py:177 +#: settings/serializers/auth/cas.py:20 terminal/models/applet/applet.py:35 +#: terminal/models/virtualapp/virtualapp.py:21 +msgid "Version" +msgstr "" + +#: accounts/models/account.py:57 accounts/serializers/account/account.py:217 +#: users/models/user.py:928 +msgid "Source" +msgstr "" + +#: accounts/models/account.py:58 +msgid "Source ID" +msgstr "" + +#: accounts/models/account.py:61 +#: accounts/serializers/automations/change_secret.py:110 +#: accounts/serializers/automations/change_secret.py:141 +#: accounts/templates/accounts/change_secret_failed_info.html:12 +#: acls/serializers/base.py:124 acls/templates/acls/asset_login_reminder.html:7 +#: assets/serializers/gateway.py:28 audits/models.py:59 +#: authentication/api/connection_token.py:411 ops/models/base.py:18 +#: perms/models/asset_permission.py:75 settings/serializers/msg.py:33 +#: terminal/backends/command/models.py:18 terminal/models/session/session.py:34 +#: terminal/serializers/command.py:72 +#: terminal/templates/terminal/_msg_command_warning.html:8 +#: terminal/templates/terminal/_msg_session_sharing.html:8 +#: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:89 +msgid "Account" +msgstr "" + +#: accounts/models/account.py:67 +msgid "Can view asset account secret" +msgstr "" + +#: accounts/models/account.py:68 +msgid "Can view asset history account" +msgstr "" + +#: accounts/models/account.py:69 +msgid "Can view asset history account secret" +msgstr "" + +#: accounts/models/account.py:70 +msgid "Can verify account" +msgstr "" + +#: accounts/models/account.py:71 +msgid "Can push account" +msgstr "" + +#: accounts/models/account.py:72 +msgid "Can remove account" +msgstr "" + +#: accounts/models/automations/backup_account.py:27 +msgid "Backup type" +msgstr "" + +#: accounts/models/automations/backup_account.py:28 +#: accounts/models/automations/backup_account.py:29 +msgid "Password divided" +msgstr "" + +#: accounts/models/automations/backup_account.py:32 +msgid "Recipient part one" +msgstr "" + +#: accounts/models/automations/backup_account.py:36 +msgid "Recipient part two" +msgstr "" + +#: accounts/models/automations/backup_account.py:40 +msgid "Object storage recipient part one" +msgstr "" + +#: accounts/models/automations/backup_account.py:44 +msgid "Object storage recipient part two" +msgstr "" + +#: accounts/models/automations/backup_account.py:47 +msgid "Zip encrypt password" +msgstr "" + +#: accounts/models/automations/backup_account.py:56 +#: accounts/models/automations/backup_account.py:139 +msgid "Account backup plan" +msgstr "" + +#: accounts/models/automations/backup_account.py:120 +#: assets/models/automations/base.py:115 audits/models.py:65 +#: ops/models/base.py:55 ops/models/celery.py:88 ops/models/job.py:241 +#: ops/templates/ops/celery_task_log.html:75 +#: perms/models/asset_permission.py:78 +#: settings/templates/ldap/_msg_import_ldap_user.html:5 +#: terminal/models/applet/host.py:141 terminal/models/session/session.py:45 +#: tickets/models/ticket/apply_application.py:30 +#: tickets/models/ticket/apply_asset.py:19 +msgid "Date start" +msgstr "" + +#: accounts/models/automations/backup_account.py:123 +#: authentication/templates/authentication/_msg_oauth_bind.html:11 +#: notifications/notifications.py:186 +#: settings/templates/ldap/_msg_import_ldap_user.html:3 +msgid "Time" +msgstr "" + +#: accounts/models/automations/backup_account.py:127 +msgid "Account backup snapshot" +msgstr "" + +#: accounts/models/automations/backup_account.py:131 +#: accounts/serializers/account/backup.py:48 +#: accounts/serializers/automations/base.py:56 +#: assets/models/automations/base.py:122 +#: assets/serializers/automations/base.py:39 +msgid "Trigger mode" +msgstr "" + +#: accounts/models/automations/backup_account.py:134 audits/models.py:203 +#: terminal/models/session/sharing.py:125 xpack/plugins/cloud/models.py:208 +msgid "Reason" +msgstr "" + +#: accounts/models/automations/backup_account.py:136 +#: accounts/serializers/automations/change_secret.py:107 +#: accounts/serializers/automations/change_secret.py:142 +#: ops/serializers/job.py:74 terminal/serializers/session.py:52 +msgid "Is success" +msgstr "" + +#: accounts/models/automations/backup_account.py:144 +msgid "Account backup execution" +msgstr "" + +#: accounts/models/automations/base.py:18 +msgid "Account automation task" +msgstr "" + +#: accounts/models/automations/base.py:32 +msgid "Automation execution" +msgstr "" + +#: accounts/models/automations/base.py:33 +msgid "Automation executions" +msgstr "" + +#: accounts/models/automations/base.py:35 +msgid "Can view change secret execution" +msgstr "" + +#: accounts/models/automations/base.py:36 +msgid "Can add change secret execution" +msgstr "" + +#: accounts/models/automations/base.py:38 +msgid "Can view gather accounts execution" +msgstr "" + +#: accounts/models/automations/base.py:39 +msgid "Can add gather accounts execution" +msgstr "" + +#: accounts/models/automations/base.py:41 +msgid "Can view push account execution" +msgstr "" + +#: accounts/models/automations/base.py:42 +msgid "Can add push account execution" +msgstr "" + +#: accounts/models/automations/base.py:54 +msgid "SSH key change strategy" +msgstr "" + +#: accounts/models/automations/change_secret.py:15 +#: accounts/models/automations/gather_account.py:58 +#: accounts/serializers/account/backup.py:40 +#: accounts/serializers/automations/change_secret.py:58 +#: settings/serializers/auth/ldap.py:90 +msgid "Recipient" +msgstr "" + +#: accounts/models/automations/change_secret.py:22 +msgid "Change secret automation" +msgstr "" + +#: accounts/models/automations/change_secret.py:39 +msgid "Old secret" +msgstr "" + +#: accounts/models/automations/change_secret.py:40 +msgid "New secret" +msgstr "" + +#: accounts/models/automations/change_secret.py:41 +msgid "Date started" +msgstr "" + +#: accounts/models/automations/change_secret.py:42 +#: assets/models/automations/base.py:116 ops/models/base.py:56 +#: ops/models/celery.py:89 ops/models/job.py:242 +#: terminal/models/applet/host.py:142 +msgid "Date finished" +msgstr "" + +#: accounts/models/automations/change_secret.py:44 +#: assets/models/automations/base.py:113 audits/models.py:208 +#: audits/serializers.py:54 ops/models/base.py:49 ops/models/job.py:233 +#: terminal/models/applet/applet.py:320 terminal/models/applet/host.py:140 +#: terminal/models/component/status.py:30 +#: terminal/models/virtualapp/virtualapp.py:99 +#: terminal/serializers/applet.py:18 terminal/serializers/applet_host.py:136 +#: terminal/serializers/virtualapp.py:35 tickets/models/ticket/general.py:281 +#: tickets/serializers/super_ticket.py:13 +#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:204 +#: xpack/plugins/cloud/models.py:260 +msgid "Status" +msgstr "" + +#: accounts/models/automations/change_secret.py:47 +#: accounts/serializers/account/account.py:262 +#: accounts/templates/accounts/change_secret_failed_info.html:13 +#: assets/const/automation.py:8 +#: authentication/templates/authentication/passkey.html:173 +#: authentication/views/base.py:42 authentication/views/base.py:43 +#: authentication/views/base.py:44 common/const/choices.py:20 +#: settings/templates/ldap/_msg_import_ldap_user.html:26 +msgid "Error" +msgstr "" + +#: accounts/models/automations/change_secret.py:51 +msgid "Change secret record" +msgstr "" + +#: accounts/models/automations/gather_account.py:14 +msgid "Present" +msgstr "" + +#: accounts/models/automations/gather_account.py:15 +msgid "Date login" +msgstr "" + +#: accounts/models/automations/gather_account.py:17 +#: accounts/models/automations/push_account.py:15 accounts/models/base.py:65 +#: accounts/serializers/account/virtual.py:21 acls/serializers/base.py:19 +#: acls/serializers/base.py:50 audits/models.py:188 authentication/forms.py:21 +#: authentication/forms.py:23 authentication/models/temp_token.py:9 +#: authentication/templates/authentication/_msg_different_city.html:9 +#: authentication/templates/authentication/_msg_oauth_bind.html:9 +#: terminal/serializers/storage.py:136 users/forms/profile.py:31 +#: users/forms/profile.py:114 users/models/user.py:872 +#: users/templates/users/_msg_user_created.html:12 +#: xpack/plugins/cloud/serializers/account_attrs.py:26 +msgid "Username" +msgstr "" + +#: accounts/models/automations/gather_account.py:18 +msgid "Address login" +msgstr "" + +#: accounts/models/automations/gather_account.py:44 +msgid "Gather account automation" +msgstr "" + +#: accounts/models/automations/gather_account.py:56 +msgid "Is sync account" +msgstr "" + +#: accounts/models/automations/gather_account.py:75 +#: accounts/tasks/gather_accounts.py:29 +msgid "Gather asset accounts" +msgstr "" + +#: accounts/models/automations/push_account.py:14 +msgid "Triggers" +msgstr "" + +#: accounts/models/automations/push_account.py:16 acls/models/base.py:41 +#: acls/serializers/base.py:57 assets/models/cmd_filter.py:81 +#: audits/models.py:92 audits/serializers.py:84 +#: authentication/serializers/connect_token_secret.py:119 +#: authentication/templates/authentication/_access_key_modal.html:34 +#: tickets/serializers/ticket/ticket.py:21 +msgid "Action" +msgstr "" + +#: accounts/models/automations/push_account.py:57 +msgid "Push asset account" +msgstr "" + +#: accounts/models/automations/verify_account.py:15 +msgid "Verify asset account" +msgstr "" + +#: accounts/models/base.py:37 accounts/models/base.py:67 +#: accounts/serializers/account/account.py:442 +#: accounts/serializers/account/base.py:17 +#: accounts/serializers/automations/change_secret.py:47 +#: authentication/serializers/connect_token_secret.py:42 +#: authentication/serializers/connect_token_secret.py:51 +#: terminal/serializers/storage.py:140 +msgid "Secret type" +msgstr "" + +#: accounts/models/base.py:39 accounts/models/mixins/vault.py:49 +#: accounts/serializers/account/base.py:20 +#: authentication/models/temp_token.py:10 +#: authentication/templates/authentication/_access_key_modal.html:31 +#: settings/serializers/auth/radius.py:19 +msgid "Secret" +msgstr "" + +#: accounts/models/base.py:42 +#: accounts/serializers/automations/change_secret.py:41 +msgid "Secret strategy" +msgstr "" + +#: accounts/models/base.py:44 accounts/serializers/account/template.py:24 +#: accounts/serializers/automations/change_secret.py:46 +msgid "Password rules" +msgstr "" + +#: accounts/models/base.py:64 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 assets/models/asset/common.py:93 +#: assets/models/asset/common.py:159 assets/models/cmd_filter.py:21 +#: assets/models/domain.py:19 assets/models/label.py:18 +#: assets/models/platform.py:15 assets/models/platform.py:94 +#: assets/serializers/asset/common.py:149 assets/serializers/platform.py:143 +#: assets/serializers/platform.py:261 +#: authentication/backends/passkey/models.py:10 +#: authentication/serializers/connect_token_secret.py:113 +#: authentication/serializers/connect_token_secret.py:169 labels/models.py:11 +#: ops/mixin.py:21 ops/models/adhoc.py:20 ops/models/celery.py:15 +#: ops/models/celery.py:80 ops/models/job.py:142 ops/models/playbook.py:28 +#: ops/serializers/job.py:18 orgs/models.py:82 +#: perms/models/asset_permission.py:61 rbac/models/role.py:29 +#: settings/models.py:34 settings/models.py:183 settings/serializers/msg.py:89 +#: settings/serializers/terminal.py:9 terminal/models/applet/applet.py:33 +#: terminal/models/component/endpoint.py:12 +#: terminal/models/component/endpoint.py:109 +#: terminal/models/component/storage.py:26 terminal/models/component/task.py:13 +#: terminal/models/component/terminal.py:85 +#: terminal/models/virtualapp/provider.py:10 +#: terminal/models/virtualapp/virtualapp.py:19 tickets/api/ticket.py:87 +#: users/forms/profile.py:32 users/models/group.py:13 +#: users/models/preference.py:11 users/models/user.py:874 +#: xpack/plugins/cloud/models.py:32 xpack/plugins/cloud/models.py:276 +#: xpack/plugins/cloud/serializers/task.py:70 +msgid "Name" +msgstr "" + +#: accounts/models/base.py:69 +msgid "Privileged" +msgstr "" + +#: accounts/models/base.py:70 assets/models/asset/common.py:165 +#: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 +#: assets/models/label.py:22 +#: authentication/serializers/connect_token_secret.py:117 +#: terminal/models/applet/applet.py:40 +#: terminal/models/component/endpoint.py:120 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:180 +msgid "Is active" +msgstr "" + +#: accounts/models/template.py:18 +msgid "Auto push" +msgstr "" + +#: accounts/models/template.py:21 +msgid "Platforms" +msgstr "" + +#: accounts/models/template.py:23 +msgid "Push params" +msgstr "" + +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:333 +msgid "Account template" +msgstr "" + +#: accounts/models/template.py:31 +msgid "Can view asset account template secret" +msgstr "" + +#: accounts/models/template.py:32 +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 "" + +#: accounts/notifications.py:12 accounts/notifications.py:37 +msgid "Notification of account backup route task results" +msgstr "" + +#: accounts/notifications.py:22 accounts/notifications.py:46 +msgid "" +"{} - The account backup passage task has been completed. See the attachment " +"for details" +msgstr "" + +#: accounts/notifications.py:25 +msgid "" +"{} - The account backup passage task has been completed: the encryption " +"password has not been set - please go to personal information -> Basic file " +"encryption password for preference settings" +msgstr "" + +#: accounts/notifications.py:56 +msgid "Notification of implementation result of encryption change plan" +msgstr "" + +#: accounts/notifications.py:67 +msgid "" +"{} - The encryption change task has been completed. See the attachment for " +"details" +msgstr "" + +#: accounts/notifications.py:71 +msgid "" +"{} - The encryption change task has been completed: the encryption password " +"has not been set - please go to personal information -> set encryption " +"password in preferences" +msgstr "" + +#: accounts/notifications.py:83 +#: accounts/templates/accounts/asset_account_change_info.html:3 +msgid "Gather account change information" +msgstr "" + +#: accounts/notifications.py:105 +msgid "Change secret or push account failed information" +msgstr "" + +#: accounts/serializers/account/account.py:31 +msgid "Push now" +msgstr "" + +#: accounts/serializers/account/account.py:36 +msgid "Params" +msgstr "" + +#: accounts/serializers/account/account.py:40 +msgid "Exist policy" +msgstr "" + +#: accounts/serializers/account/account.py:195 assets/models/label.py:21 +#: assets/models/platform.py:95 assets/serializers/asset/common.py:125 +#: assets/serializers/cagegory.py:12 assets/serializers/platform.py:165 +#: assets/serializers/platform.py:262 perms/serializers/user_permission.py:26 +#: settings/models.py:36 tickets/models/ticket/apply_application.py:13 +#: users/models/preference.py:12 +msgid "Category" +msgstr "" + +#: accounts/serializers/account/account.py:196 +#: accounts/serializers/automations/base.py:55 acls/models/command_acl.py:24 +#: acls/serializers/command_acl.py:19 assets/models/automations/base.py:20 +#: assets/models/cmd_filter.py:74 assets/models/platform.py:96 +#: assets/serializers/asset/common.py:126 assets/serializers/platform.py:145 +#: assets/serializers/platform.py:164 audits/serializers.py:53 +#: audits/serializers.py:170 +#: authentication/serializers/connect_token_secret.py:126 ops/models/job.py:150 +#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:39 +#: terminal/models/component/storage.py:57 +#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29 +#: terminal/serializers/session.py:23 terminal/serializers/storage.py:264 +#: terminal/serializers/storage.py:276 tickets/models/comment.py:26 +#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16 +#: tickets/models/ticket/general.py:273 tickets/serializers/flow.py:53 +#: tickets/serializers/ticket/ticket.py:19 +msgid "Type" +msgstr "" + +#: accounts/serializers/account/account.py:211 +msgid "Asset not found" +msgstr "" + +#: accounts/serializers/account/account.py:251 +msgid "Has secret" +msgstr "" + +#: accounts/serializers/account/account.py:261 ops/models/celery.py:83 +#: tickets/models/comment.py:13 tickets/models/ticket/general.py:46 +#: tickets/models/ticket/general.py:277 tickets/serializers/super_ticket.py:14 +msgid "State" +msgstr "" + +#: accounts/serializers/account/account.py:263 +msgid "Changed" +msgstr "" + +#: accounts/serializers/account/account.py:273 +#: accounts/serializers/automations/base.py:22 acls/models/base.py:97 +#: acls/templates/acls/asset_login_reminder.html:6 +#: assets/models/automations/base.py:19 +#: assets/serializers/automations/base.py:20 +#: authentication/api/connection_token.py:410 ops/models/base.py:17 +#: ops/models/job.py:152 ops/serializers/job.py:19 +#: perms/serializers/permission.py:36 +#: terminal/templates/terminal/_msg_command_execute_alert.html:16 +msgid "Assets" +msgstr "" + +#: accounts/serializers/account/account.py:328 +msgid "Account already exists" +msgstr "" + +#: accounts/serializers/account/account.py:378 +#, python-format +msgid "Asset does not support this secret type: %s" +msgstr "" + +#: accounts/serializers/account/account.py:410 +msgid "Account has exist" +msgstr "" + +#: accounts/serializers/account/account.py:443 +#: authentication/serializers/connect_token_secret.py:159 +#: authentication/templates/authentication/_access_key_modal.html:30 +#: perms/models/perm_node.py:21 users/serializers/group.py:33 +msgid "ID" +msgstr "" + +#: accounts/serializers/account/account.py:453 acls/serializers/base.py:116 +#: acls/templates/acls/asset_login_reminder.html:5 +#: acls/templates/acls/user_login_reminder.html:5 +#: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:54 +#: audits/models.py:90 audits/models.py:172 audits/models.py:269 +#: audits/serializers.py:171 authentication/models/connection_token.py:32 +#: authentication/models/sso_token.py:16 +#: notifications/models/notification.py:12 +#: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:63 +#: rbac/builtin.py:124 rbac/models/rolebinding.py:49 +#: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 +#: terminal/models/session/session.py:30 terminal/models/session/sharing.py:34 +#: terminal/notifications.py:156 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:1062 +#: users/models/user.py:1100 +msgid "User" +msgstr "" + +#: accounts/serializers/account/account.py:454 +#: authentication/templates/authentication/_access_key_modal.html:33 +#: terminal/notifications.py:158 terminal/notifications.py:207 +msgid "Date" +msgstr "" + +#: accounts/serializers/account/backup.py:20 +msgid "Zip Encrypt Password" +msgstr "" + +#: accounts/serializers/account/backup.py:38 +#: accounts/serializers/automations/base.py:38 +msgid "Executions" +msgstr "" + +#: accounts/serializers/account/backup.py:41 +#: accounts/serializers/automations/change_secret.py:59 +msgid "Currently only mail sending is supported" +msgstr "" + +#: accounts/serializers/account/backup.py:43 +msgid "Asset type" +msgstr "" + +#: accounts/serializers/account/base.py:25 terminal/serializers/storage.py:149 +msgid "Passphrase" +msgstr "" + +#: accounts/serializers/account/base.py:78 +#: assets/serializers/asset/common.py:384 +msgid "Spec info" +msgstr "" + +#: accounts/serializers/account/base.py:80 +msgid "" +"Tip: If no username is required for authentication, fill in `null`, If AD " +"account, like `username@domain`" +msgstr "" + +#: accounts/serializers/account/template.py:13 +msgid "Password length" +msgstr "" + +#: accounts/serializers/account/template.py:14 +#: settings/serializers/security.py:44 +msgid "Lowercase" +msgstr "" + +#: accounts/serializers/account/template.py:15 +#: settings/serializers/security.py:41 +msgid "Uppercase" +msgstr "" + +#: accounts/serializers/account/template.py:16 +msgid "Digit" +msgstr "" + +#: accounts/serializers/account/template.py:17 +msgid "Special symbol" +msgstr "" + +#: accounts/serializers/account/template.py:19 +msgid "Exclude symbol" +msgstr "" + +#: accounts/serializers/account/template.py:38 +msgid "Secret generation strategy for account creation" +msgstr "" + +#: accounts/serializers/account/template.py:39 +msgid "Whether to automatically push the account to the asset" +msgstr "" + +#: accounts/serializers/account/template.py:42 +msgid "" +"Associated platform, you can configure push parameters. If not associated, " +"default parameters will be used" +msgstr "" + +#: accounts/serializers/account/virtual.py:19 assets/models/cmd_filter.py:40 +#: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:26 +#: ops/models/job.py:158 ops/models/playbook.py:31 rbac/models/role.py:37 +#: settings/models.py:39 terminal/models/applet/applet.py:45 +#: terminal/models/applet/applet.py:321 terminal/models/applet/host.py:143 +#: terminal/models/component/endpoint.py:25 +#: terminal/models/component/endpoint.py:119 +#: terminal/models/session/session.py:47 +#: terminal/models/virtualapp/virtualapp.py:28 tickets/models/comment.py:32 +#: tickets/models/ticket/general.py:295 users/models/user.py:910 +#: xpack/plugins/cloud/models.py:39 xpack/plugins/cloud/models.py:110 +msgid "Comment" +msgstr "" + +#: accounts/serializers/account/virtual.py:24 +msgid "" +"Current only support login from AD/LDAP. Secret priority: Same account in " +"asset secret > Login secret > Manual input.
For security, please set " +"config CACHE_LOGIN_PASSWORD_ENABLED to true" +msgstr "" + +#: accounts/serializers/automations/base.py:23 +#: assets/models/asset/common.py:164 assets/serializers/asset/common.py:152 +#: assets/serializers/automations/base.py:21 perms/serializers/permission.py:37 +msgid "Nodes" +msgstr "" + +#: accounts/serializers/automations/base.py:24 +msgid "Periodic perform" +msgstr "" + +#: accounts/serializers/automations/base.py:45 +msgid "Name already exists" +msgstr "" + +#: accounts/serializers/automations/base.py:54 +#: assets/models/automations/base.py:118 +#: assets/serializers/automations/base.py:38 +msgid "Automation snapshot" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:44 +msgid "SSH Key strategy" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:81 +msgid "* Please enter the correct password length" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:85 +msgid "* Password length range 6-30 bits" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:114 +#: assets/models/automations/base.py:127 +msgid "Automation task execution" +msgstr "" + +#: accounts/signal_handlers.py:47 +#, python-format +msgid "Push related accounts to assets: %s, by system" +msgstr "" + +#: accounts/signal_handlers.py:56 +#, python-format +msgid "Add account: %s" +msgstr "" + +#: accounts/signal_handlers.py:58 +#, python-format +msgid "Delete account: %s" +msgstr "" + +#: accounts/tasks/automation.py:25 +msgid "Account execute automation" +msgstr "" + +#: accounts/tasks/automation.py:51 accounts/tasks/automation.py:56 +msgid "Execute automation record" +msgstr "" + +#: accounts/tasks/backup_account.py:25 +msgid "Execute account backup plan" +msgstr "" + +#: accounts/tasks/gather_accounts.py:34 +msgid "Gather assets accounts" +msgstr "" + +#: accounts/tasks/push_account.py:15 accounts/tasks/push_account.py:23 +msgid "Push accounts to assets" +msgstr "" + +#: accounts/tasks/remove_account.py:44 +msgid "Clean historical accounts" +msgstr "" + +#: accounts/tasks/remove_account.py:76 +msgid "Remove historical accounts that are out of range." +msgstr "" + +#: accounts/tasks/template.py:11 +msgid "Template sync info to related accounts" +msgstr "" + +#: accounts/tasks/vault.py:31 +msgid "Sync secret to vault" +msgstr "" + +#: accounts/tasks/verify_account.py:49 +msgid "Verify asset account availability" +msgstr "" + +#: accounts/tasks/verify_account.py:55 +msgid "Verify accounts connectivity" +msgstr "" + +#: accounts/templates/accounts/asset_account_change_info.html:8 +msgid "Added account" +msgstr "" + +#: accounts/templates/accounts/asset_account_change_info.html:9 +msgid "Deleted account" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:3 +#: ops/templates/ops/celery_task_log.html:71 terminal/serializers/task.py:10 +msgid "Task name" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:4 +msgid "Task execution id" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:5 +#: acls/templates/acls/asset_login_reminder.html:3 +#: acls/templates/acls/user_login_reminder.html:3 +msgid "Respectful" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:6 +msgid "" +"Hello! The following is the failure of changing the password of your assets " +"or pushing the account. Please check and handle it in time." +msgstr "" + +#: accounts/utils.py:52 +msgid "" +"If the password starts with {{` and ends with }} `, then the password is not " +"allowed." +msgstr "" + +#: accounts/utils.py:59 +msgid "private key invalid or passphrase error" +msgstr "" + +#: acls/apps.py:7 +msgid "App Acls" +msgstr "" + +#: acls/const.py:6 audits/const.py:36 terminal/const.py:11 tickets/const.py:44 +#: tickets/templates/tickets/approve_check_password.html:47 +msgid "Reject" +msgstr "" + +#: acls/const.py:7 audits/const.py:33 terminal/const.py:9 +msgid "Accept" +msgstr "" + +#: acls/const.py:8 audits/const.py:34 +msgid "Review" +msgstr "" + +#: acls/const.py:9 +msgid "Warn" +msgstr "" + +#: acls/const.py:10 +msgid "Notify" +msgstr "" + +#: acls/models/base.py:37 assets/models/cmd_filter.py:76 +#: terminal/models/component/endpoint.py:112 xpack/plugins/cloud/models.py:282 +msgid "Priority" +msgstr "" + +#: acls/models/base.py:38 assets/models/cmd_filter.py:76 +#: terminal/models/component/endpoint.py:113 xpack/plugins/cloud/models.py:283 +msgid "1-100, the lower the value will be match first" +msgstr "" + +#: acls/models/base.py:42 assets/models/cmd_filter.py:86 +#: authentication/serializers/connect_token_secret.py:91 +msgid "Reviewers" +msgstr "" + +#: acls/models/base.py:43 authentication/models/access_key.py:25 +#: authentication/models/connection_token.py:53 +#: authentication/templates/authentication/_access_key_modal.html:32 +#: perms/models/asset_permission.py:82 terminal/models/session/sharing.py:29 +#: tickets/const.py:36 +msgid "Active" +msgstr "" + +#: acls/models/base.py:81 perms/serializers/permission.py:32 +#: users/models/preference.py:16 users/serializers/group.py:21 +#: users/serializers/user.py:311 +msgid "Users" +msgstr "" + +#: acls/models/base.py:98 assets/models/automations/base.py:17 +#: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:128 +#: perms/serializers/permission.py:45 perms/serializers/user_permission.py:75 +#: rbac/tree.py:35 +msgid "Accounts" +msgstr "" + +#: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 +#: ops/serializers/job.py:73 terminal/const.py:86 +#: terminal/models/session/session.py:43 terminal/serializers/command.py:18 +#: terminal/templates/terminal/_msg_command_alert.html:12 +#: terminal/templates/terminal/_msg_command_execute_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:23 +msgid "Command" +msgstr "" + +#: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 +#: xpack/plugins/cloud/models.py:299 +msgid "Regex" +msgstr "" + +#: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79 +#: settings/models.py:184 settings/serializers/feature.py:19 +#: settings/serializers/msg.py:78 xpack/plugins/license/models.py:30 +msgid "Content" +msgstr "" + +#: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79 +msgid "One line one command" +msgstr "" + +#: acls/models/command_acl.py:27 assets/models/cmd_filter.py:80 +msgid "Ignore case" +msgstr "" + +#: acls/models/command_acl.py:33 acls/models/command_acl.py:97 +#: acls/serializers/command_acl.py:29 +#: authentication/serializers/connect_token_secret.py:88 +#: terminal/templates/terminal/_msg_command_warning.html:14 +msgid "Command group" +msgstr "" + +#: acls/models/command_acl.py:86 +msgid "The generated regular expression is incorrect: {}" +msgstr "" + +#: acls/models/command_acl.py:103 +#: terminal/templates/terminal/_msg_command_warning.html:12 +msgid "Command acl" +msgstr "" + +#: acls/models/command_acl.py:112 tickets/const.py:12 +msgid "Command confirm" +msgstr "" + +#: acls/models/connect_method.py:10 +msgid "Connect methods" +msgstr "" + +#: acls/models/connect_method.py:13 +msgid "Connect method acl" +msgstr "" + +#: acls/models/login_acl.py:11 acls/models/login_asset_acl.py:9 +#: acls/serializers/login_acl.py:15 acls/serializers/login_asset_acl.py:13 +msgid "Rule" +msgstr "" + +#: acls/models/login_acl.py:14 +msgid "Login acl" +msgstr "" + +#: acls/models/login_acl.py:27 tickets/const.py:11 +msgid "Login confirm" +msgstr "" + +#: acls/models/login_asset_acl.py:12 +msgid "Login asset acl" +msgstr "" + +#: acls/models/login_asset_acl.py:22 tickets/const.py:13 +msgid "Login asset confirm" +msgstr "" + +#: acls/notifications.py:12 +msgid "User login reminder" +msgstr "" + +#: acls/notifications.py:42 +msgid "Asset login reminder" +msgstr "" + +#: acls/serializers/base.py:11 acls/serializers/login_acl.py:11 +msgid "With * indicating a match all. " +msgstr "" + +#: acls/serializers/base.py:26 +msgid "" +"With * indicating a match all. Such as: 192.168.10.1, 192.168.1.0/24, " +"10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 (Domain name " +"support)" +msgstr "" + +#: acls/serializers/base.py:41 assets/serializers/asset/host.py:19 +msgid "IP/Host" +msgstr "" + +#: acls/serializers/base.py:91 +msgid "Recipients" +msgstr "" + +#: acls/serializers/base.py:103 tickets/serializers/ticket/ticket.py:77 +msgid "The organization `{}` does not exist" +msgstr "" + +#: acls/serializers/base.py:109 +msgid "None of the reviewers belong to Organization `{}`" +msgstr "" + +#: acls/serializers/rules/rules.py:20 +#: xpack/plugins/cloud/serializers/task.py:145 +msgid "IP address invalid: `{}`" +msgstr "" + +#: acls/serializers/rules/rules.py:25 +msgid "" +"With * indicating a match all. Such as: 192.168.10.1, 192.168.1.0/24, " +"10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 " +msgstr "" + +#: acls/serializers/rules/rules.py:33 +#: authentication/templates/authentication/_msg_oauth_bind.html:12 +#: authentication/templates/authentication/_msg_rest_password_success.html:8 +#: authentication/templates/authentication/_msg_rest_public_key_success.html:8 +msgid "IP" +msgstr "" + +#: acls/serializers/rules/rules.py:35 +msgid "Time Period" +msgstr "" + +#: acls/templates/acls/asset_login_reminder.html:10 +msgid "" +"The user has just logged in to the asset. Please ensure that this is an " +"authorized operation. If you suspect that this is an unauthorized access, " +"please take appropriate measures immediately." +msgstr "" + +#: acls/templates/acls/asset_login_reminder.html:12 +#: acls/templates/acls/user_login_reminder.html:13 +msgid "Thank you" +msgstr "" + +#: acls/templates/acls/user_login_reminder.html:7 audits/models.py:194 +#: audits/models.py:263 +#: authentication/templates/authentication/_msg_different_city.html:11 +#: tickets/models/ticket/login_confirm.py:11 +msgid "Login city" +msgstr "" + +#: acls/templates/acls/user_login_reminder.html:8 audits/models.py:197 +#: audits/models.py:264 audits/serializers.py:68 +msgid "User agent" +msgstr "" + +#: acls/templates/acls/user_login_reminder.html:11 +msgid "" +"The user has just successfully logged into the system. Please ensure that " +"this is an authorized operation. If you suspect that this is an unauthorized " +"access, please take appropriate measures immediately." +msgstr "" + +#: assets/api/asset/asset.py:180 +msgid "Cannot create asset directly, you should create a host or other" +msgstr "" + +#: assets/api/domain.py:67 +msgid "Number required" +msgstr "" + +#: assets/api/node.py:58 +msgid "You can't update the root node name" +msgstr "" + +#: assets/api/node.py:65 +msgid "You can't delete the root node ({})" +msgstr "" + +#: assets/api/node.py:68 +msgid "Deletion failed and the node contains assets" +msgstr "" + +#: assets/api/tree.py:49 assets/serializers/node.py:42 +msgid "The same level node name cannot be the same" +msgstr "" + +#: assets/apps.py:9 +msgid "App Assets" +msgstr "" + +#: assets/automations/base/manager.py:191 +msgid "{} disabled" +msgstr "" + +#: assets/automations/base/manager.py:254 +msgid " - Platform {} ansible disabled" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:33 +#: authentication/models/connection_token.py:131 +msgid "No account" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:36 +msgid "Asset, {}, using account {}" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:55 +#, python-brace-format +msgid "Unable to connect to port {port} on {address}" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:58 +#: authentication/backends/oauth2/views.py:60 authentication/middleware.py:93 +#: xpack/plugins/cloud/providers/fc.py:47 +msgid "Authentication failed" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:60 +#: assets/automations/ping_gateway/manager.py:86 terminal/const.py:102 +msgid "Connect failed" +msgstr "" + +#: assets/const/automation.py:6 audits/const.py:6 audits/const.py:44 +#: audits/signal_handlers/activity_log.py:62 common/utils/ip/geoip/utils.py:31 +#: common/utils/ip/geoip/utils.py:37 common/utils/ip/utils.py:104 +msgid "Unknown" +msgstr "" + +#: assets/const/automation.py:7 +msgid "Ok" +msgstr "" + +#: assets/const/automation.py:12 +msgid "Ping" +msgstr "" + +#: assets/const/automation.py:13 +msgid "Ping gateway" +msgstr "" + +#: assets/const/automation.py:14 +msgid "Gather facts" +msgstr "" + +#: assets/const/base.py:32 audits/const.py:55 +#: terminal/serializers/applet_host.py:32 +msgid "Disabled" +msgstr "" + +#: assets/const/base.py:33 settings/serializers/basic.py:8 +#: users/serializers/preference/koko.py:19 +#: users/serializers/preference/lina.py:39 +#: users/serializers/preference/luna.py:77 +msgid "Basic" +msgstr "" + +#: assets/const/base.py:34 assets/const/protocol.py:268 +#: assets/models/asset/web.py:13 +msgid "Script" +msgstr "" + +#: assets/const/category.py:10 assets/models/asset/host.py:8 +#: settings/serializers/auth/radius.py:16 settings/serializers/auth/sms.py:71 +#: settings/serializers/feature.py:49 settings/serializers/msg.py:31 +#: terminal/models/component/endpoint.py:13 terminal/serializers/applet.py:17 +#: xpack/plugins/cloud/serializers/account_attrs.py:72 +msgid "Host" +msgstr "" + +#: assets/const/category.py:11 assets/models/asset/device.py:8 +msgid "Device" +msgstr "" + +#: assets/const/category.py:13 +msgid "Cloud service" +msgstr "" + +#: assets/const/category.py:14 assets/models/asset/gpt.py:11 +#: assets/models/asset/web.py:16 audits/const.py:42 +#: terminal/models/applet/applet.py:27 users/const.py:64 +msgid "Web" +msgstr "" + +#: assets/const/category.py:16 common/sdk/sms/endpoint.py:20 +msgid "Custom type" +msgstr "" + +#: assets/const/cloud.py:7 +msgid "Public cloud" +msgstr "" + +#: assets/const/cloud.py:8 +msgid "Private cloud" +msgstr "" + +#: assets/const/cloud.py:9 +msgid "Kubernetes" +msgstr "" + +#: assets/const/device.py:7 terminal/models/applet/applet.py:26 +#: tickets/const.py:9 +msgid "General" +msgstr "" + +#: assets/const/device.py:8 +msgid "Switch" +msgstr "" + +#: assets/const/device.py:9 +msgid "Router" +msgstr "" + +#: assets/const/device.py:10 +msgid "Firewall" +msgstr "" + +#: assets/const/gpt.py:7 +msgid "ChatGPT" +msgstr "" + +#: assets/const/host.py:12 rbac/tree.py:28 +msgid "Other" +msgstr "" + +#: assets/const/protocol.py:45 +msgid "Old SSH version" +msgstr "" + +#: assets/const/protocol.py:46 +msgid "Old SSH version like openssh 5.x or 6.x" +msgstr "" + +#: assets/const/protocol.py:57 +msgid "SFTP root" +msgstr "" + +#: assets/const/protocol.py:59 +#, python-brace-format +msgid "" +"SFTP root directory, Support variable:
- ${ACCOUNT} The connected " +"account username
- ${HOME} The home directory of the connected account " +"
- ${USER} The username of the user" +msgstr "" + +#: assets/const/protocol.py:74 +msgid "Console" +msgstr "" + +#: assets/const/protocol.py:75 +msgid "Connect to console session" +msgstr "" + +#: assets/const/protocol.py:79 +msgid "Any" +msgstr "" + +#: assets/const/protocol.py:81 settings/serializers/security.py:232 +msgid "Security" +msgstr "" + +#: assets/const/protocol.py:82 +msgid "Security layer to use for the connection" +msgstr "" + +#: assets/const/protocol.py:88 +msgid "AD domain" +msgstr "" + +#: assets/const/protocol.py:103 +msgid "Username prompt" +msgstr "" + +#: assets/const/protocol.py:104 +msgid "We will send username when we see this prompt" +msgstr "" + +#: assets/const/protocol.py:109 +msgid "Password prompt" +msgstr "" + +#: assets/const/protocol.py:110 +msgid "We will send password when we see this prompt" +msgstr "" + +#: assets/const/protocol.py:115 +msgid "Success prompt" +msgstr "" + +#: assets/const/protocol.py:116 +msgid "We will consider login success when we see this prompt" +msgstr "" + +#: assets/const/protocol.py:127 assets/models/asset/database.py:10 +#: settings/serializers/msg.py:47 +msgid "Use SSL" +msgstr "" + +#: assets/const/protocol.py:162 +msgid "SYSDBA" +msgstr "" + +#: assets/const/protocol.py:163 +msgid "Connect as SYSDBA" +msgstr "" + +#: assets/const/protocol.py:178 +msgid "" +"SQL Server version, Different versions have different connection drivers" +msgstr "" + +#: assets/const/protocol.py:202 +msgid "Auth source" +msgstr "" + +#: assets/const/protocol.py:203 +msgid "The database to authenticate against" +msgstr "" + +#: assets/const/protocol.py:215 +msgid "Auth username" +msgstr "" + +#: assets/const/protocol.py:238 +msgid "Safe mode" +msgstr "" + +#: assets/const/protocol.py:240 +msgid "" +"When safe mode is enabled, some operations will be disabled, such as: New " +"tab, right click, visit other website, etc." +msgstr "" + +#: assets/const/protocol.py:245 assets/models/asset/web.py:9 +#: assets/serializers/asset/info/spec.py:16 +msgid "Autofill" +msgstr "" + +#: assets/const/protocol.py:253 assets/models/asset/web.py:10 +msgid "Username selector" +msgstr "" + +#: assets/const/protocol.py:258 assets/models/asset/web.py:11 +msgid "Password selector" +msgstr "" + +#: assets/const/protocol.py:263 assets/models/asset/web.py:12 +msgid "Submit selector" +msgstr "" + +#: assets/const/protocol.py:286 +msgid "API mode" +msgstr "" + +#: assets/const/types.py:251 +msgid "All types" +msgstr "" + +#: assets/const/web.py:7 +msgid "Website" +msgstr "" + +#: assets/exceptions.py:12 +msgid "This function is not supported temporarily" +msgstr "" + +#: assets/models/asset/cloud.py:11 +msgid "Cloud" +msgstr "" + +#: assets/models/asset/common.py:94 assets/models/platform.py:16 +#: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:72 +#: settings/serializers/msg.py:32 terminal/serializers/storage.py:133 +#: xpack/plugins/cloud/serializers/account_attrs.py:73 +msgid "Port" +msgstr "" + +#: assets/models/asset/common.py:160 assets/serializers/asset/common.py:150 +#: settings/serializers/terminal.py:10 +msgid "Address" +msgstr "" + +#: assets/models/asset/common.py:161 assets/models/platform.py:134 +#: authentication/backends/passkey/models.py:12 +#: authentication/serializers/connect_token_secret.py:118 +#: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:329 +msgid "Platform" +msgstr "" + +#: assets/models/asset/common.py:163 +#: authentication/serializers/connect_token_secret.py:136 +#: perms/serializers/user_permission.py:28 xpack/plugins/cloud/models.py:331 +msgid "Domain" +msgstr "" + +#: assets/models/asset/common.py:166 assets/serializers/asset/common.py:385 +#: assets/serializers/asset/host.py:11 +msgid "Gathered info" +msgstr "" + +#: assets/models/asset/common.py:167 assets/serializers/asset/custom.py:14 +msgid "Custom info" +msgstr "" + +#: assets/models/asset/common.py:352 +msgid "Can refresh asset hardware info" +msgstr "" + +#: assets/models/asset/common.py:353 +msgid "Can test asset connectivity" +msgstr "" + +#: assets/models/asset/common.py:354 +msgid "Can match asset" +msgstr "" + +#: assets/models/asset/common.py:355 +msgid "Can change asset nodes" +msgstr "" + +#: assets/models/asset/custom.py:8 +msgid "Custom asset" +msgstr "" + +#: assets/models/asset/database.py:11 +msgid "CA cert" +msgstr "" + +#: assets/models/asset/database.py:12 +msgid "Client cert" +msgstr "" + +#: assets/models/asset/database.py:13 +msgid "Client key" +msgstr "" + +#: assets/models/asset/database.py:14 +msgid "Allow invalid cert" +msgstr "" + +#: assets/models/asset/gpt.py:8 settings/serializers/feature.py:84 +msgid "Proxy" +msgstr "" + +#: assets/models/automations/base.py:18 assets/models/cmd_filter.py:32 +#: assets/models/node.py:553 perms/models/asset_permission.py:72 +#: tickets/models/ticket/apply_asset.py:14 xpack/plugins/cloud/models.py:330 +msgid "Node" +msgstr "" + +#: assets/models/automations/base.py:22 ops/models/job.py:236 +#: settings/serializers/auth/sms.py:103 +msgid "Parameters" +msgstr "" + +#: assets/models/automations/base.py:29 assets/models/automations/base.py:111 +msgid "Automation task" +msgstr "" + +#: assets/models/automations/base.py:104 +msgid "Asset automation task" +msgstr "" + +#: assets/models/automations/base.py:114 assets/models/cmd_filter.py:41 +#: audits/models.py:267 common/db/models.py:34 ops/models/base.py:54 +#: ops/models/job.py:240 users/models/user.py:1101 +msgid "Date created" +msgstr "" + +#: assets/models/automations/gather_facts.py:15 +msgid "Gather asset facts" +msgstr "" + +#: assets/models/automations/ping.py:15 +msgid "Ping asset" +msgstr "" + +#: assets/models/base.py:19 terminal/notifications.py:225 +msgid "Connectivity" +msgstr "" + +#: assets/models/base.py:21 authentication/models/temp_token.py:12 +msgid "Date verified" +msgstr "" + +#: assets/models/cmd_filter.py:28 perms/models/asset_permission.py:66 +#: users/models/group.py:25 users/models/user.py:880 +msgid "User group" +msgstr "" + +#: assets/models/cmd_filter.py:42 common/db/models.py:35 +#: users/models/user.py:936 +msgid "Date updated" +msgstr "" + +#: assets/models/cmd_filter.py:44 assets/models/cmd_filter.py:91 +#: common/db/models.py:32 users/models/user.py:917 +#: users/serializers/group.py:32 +msgid "Created by" +msgstr "" + +#: assets/models/cmd_filter.py:52 +msgid "Command filter" +msgstr "" + +#: assets/models/cmd_filter.py:66 +msgid "Deny" +msgstr "" + +#: assets/models/cmd_filter.py:67 +msgid "Allow" +msgstr "" + +#: assets/models/cmd_filter.py:68 +msgid "Reconfirm" +msgstr "" + +#: assets/models/cmd_filter.py:72 +msgid "Filter" +msgstr "" + +#: assets/models/cmd_filter.py:95 +msgid "Command filter rule" +msgstr "" + +#: assets/models/domain.py:22 +msgid "Zone" +msgstr "" + +#: assets/models/favorite_asset.py:17 +msgid "Favorite asset" +msgstr "" + +#: assets/models/gateway.py:34 assets/serializers/domain.py:19 +msgid "Gateway" +msgstr "" + +#: assets/models/label.py:15 rbac/const.py:6 users/models/user.py:1086 +msgid "System" +msgstr "" + +#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 +#: assets/serializers/cagegory.py:24 +#: authentication/models/connection_token.py:29 +#: authentication/serializers/connect_token_secret.py:125 +#: common/serializers/common.py:86 labels/models.py:12 settings/models.py:35 +#: users/models/preference.py:13 +msgid "Value" +msgstr "" + +#: assets/models/label.py:40 assets/serializers/cagegory.py:10 +#: assets/serializers/cagegory.py:17 assets/serializers/cagegory.py:23 +#: assets/serializers/platform.py:144 +#: authentication/serializers/connect_token_secret.py:124 +#: common/serializers/common.py:85 labels/models.py:17 labels/models.py:33 +#: labels/serializers.py:45 settings/serializers/msg.py:90 +msgid "Label" +msgstr "" + +#: assets/models/node.py:169 +msgid "New node" +msgstr "" + +#: assets/models/node.py:467 audits/backends/db.py:65 audits/backends/db.py:66 +msgid "empty" +msgstr "" + +#: assets/models/node.py:538 perms/models/perm_node.py:28 +msgid "Key" +msgstr "" + +#: assets/models/node.py:540 assets/serializers/node.py:20 +msgid "Full value" +msgstr "" + +#: assets/models/node.py:544 perms/models/perm_node.py:30 +msgid "Parent key" +msgstr "" + +#: assets/models/node.py:556 +msgid "Can match node" +msgstr "" + +#: assets/models/platform.py:17 +msgid "Primary" +msgstr "" + +#: assets/models/platform.py:18 +msgid "Required" +msgstr "" + +#: assets/models/platform.py:19 assets/serializers/platform.py:146 +#: xpack/plugins/cloud/providers/nutanix.py:30 +msgid "Default" +msgstr "" + +#: assets/models/platform.py:20 +msgid "Public" +msgstr "" + +#: assets/models/platform.py:21 assets/serializers/platform.py:74 +#: settings/serializers/settings.py:95 +#: users/templates/users/reset_password.html:29 +msgid "Setting" +msgstr "" + +#: assets/models/platform.py:38 audits/const.py:56 +#: authentication/backends/passkey/models.py:11 settings/models.py:38 +#: terminal/serializers/applet_host.py:33 +msgid "Enabled" +msgstr "" + +#: assets/models/platform.py:39 +msgid "Ansible config" +msgstr "" + +#: assets/models/platform.py:41 assets/serializers/platform.py:33 +msgid "Ping enabled" +msgstr "" + +#: assets/models/platform.py:42 assets/serializers/platform.py:34 +msgid "Ping method" +msgstr "" + +#: assets/models/platform.py:43 +msgid "Ping params" +msgstr "" + +#: assets/models/platform.py:45 assets/models/platform.py:69 +#: assets/serializers/platform.py:36 +msgid "Gather facts enabled" +msgstr "" + +#: assets/models/platform.py:47 assets/models/platform.py:71 +#: assets/serializers/platform.py:40 +msgid "Gather facts method" +msgstr "" + +#: assets/models/platform.py:49 assets/models/platform.py:73 +msgid "Gather facts params" +msgstr "" + +#: assets/models/platform.py:51 assets/serializers/platform.py:50 +msgid "Change secret enabled" +msgstr "" + +#: assets/models/platform.py:53 assets/serializers/platform.py:54 +msgid "Change secret method" +msgstr "" + +#: assets/models/platform.py:55 +msgid "Change secret params" +msgstr "" + +#: assets/models/platform.py:57 assets/serializers/platform.py:57 +msgid "Push account enabled" +msgstr "" + +#: assets/models/platform.py:59 assets/serializers/platform.py:61 +msgid "Push account method" +msgstr "" + +#: assets/models/platform.py:61 +msgid "Push account params" +msgstr "" + +#: assets/models/platform.py:63 assets/serializers/platform.py:43 +msgid "Verify account enabled" +msgstr "" + +#: assets/models/platform.py:65 assets/serializers/platform.py:47 +msgid "Verify account method" +msgstr "" + +#: assets/models/platform.py:67 +msgid "Verify account params" +msgstr "" + +#: assets/models/platform.py:75 +msgid "Remove account enabled" +msgstr "" + +#: assets/models/platform.py:77 +msgid "Remove account method" +msgstr "" + +#: assets/models/platform.py:79 +msgid "Remove account params" +msgstr "" + +#: assets/models/platform.py:97 tickets/models/ticket/general.py:298 +msgid "Meta" +msgstr "" + +#: assets/models/platform.py:98 labels/models.py:13 +msgid "Internal" +msgstr "" + +#: assets/models/platform.py:102 assets/serializers/platform.py:163 +msgid "Charset" +msgstr "" + +#: assets/models/platform.py:104 assets/serializers/platform.py:198 +msgid "Domain enabled" +msgstr "" + +#: assets/models/platform.py:106 assets/serializers/platform.py:191 +msgid "Su enabled" +msgstr "" + +#: assets/models/platform.py:107 assets/serializers/platform.py:169 +msgid "Su method" +msgstr "" + +#: assets/models/platform.py:108 assets/serializers/platform.py:172 +msgid "Custom fields" +msgstr "" + +#: assets/models/utils.py:18 +#, python-format +msgid "%(value)s is not an even number" +msgstr "" + +#: assets/notifications.py:12 +msgid "" +"Batch update platform in assets, skipping assets that do not meet platform " +"type" +msgstr "" + +#: assets/serializers/asset/common.py:127 assets/serializers/platform.py:166 +#: authentication/serializers/connect_token_secret.py:30 +#: authentication/serializers/connect_token_secret.py:75 +#: perms/models/asset_permission.py:76 perms/serializers/permission.py:46 +#: perms/serializers/user_permission.py:74 xpack/plugins/cloud/models.py:332 +#: xpack/plugins/cloud/serializers/task.py:33 +msgid "Protocols" +msgstr "" + +#: assets/serializers/asset/common.py:129 +#: assets/serializers/asset/common.py:151 +msgid "Node path" +msgstr "" + +#: assets/serializers/asset/common.py:148 +#: assets/serializers/asset/common.py:386 +msgid "Auto info" +msgstr "" + +#: assets/serializers/asset/common.py:245 +msgid "Platform not exist" +msgstr "" + +#: assets/serializers/asset/common.py:281 +msgid "port out of range (0-65535)" +msgstr "" + +#: assets/serializers/asset/common.py:288 +msgid "Protocol is required: {}" +msgstr "" + +#: assets/serializers/asset/common.py:316 +msgid "Invalid data" +msgstr "" + +#: assets/serializers/asset/database.py:13 +msgid "Default database" +msgstr "" + +#: assets/serializers/asset/gpt.py:20 +msgid "" +"If the server cannot directly connect to the API address, you need set up an " +"HTTP proxy. e.g. http(s)://host:port" +msgstr "" + +#: assets/serializers/asset/gpt.py:24 +msgid "HTTP proxy" +msgstr "" + +#: assets/serializers/asset/gpt.py:31 +msgid "Proxy must start with http:// or https://" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:6 +msgid "Vendor" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:7 +msgid "Model" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:8 +#: tickets/models/ticket/general.py:297 +msgid "Serial number" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:9 +msgid "CPU model" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:10 +msgid "CPU count" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:11 +msgid "CPU cores" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:12 +msgid "CPU vcpus" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:13 +msgid "Memory" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:14 +msgid "Disk total" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:16 +#: authentication/serializers/connect_token_secret.py:115 +msgid "OS" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:17 +msgid "OS version" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:18 +msgid "OS arch" +msgstr "" + +#: assets/serializers/cagegory.py:13 +msgid "Constraints" +msgstr "" + +#: assets/serializers/cagegory.py:19 +msgid "Types" +msgstr "" + +#: assets/serializers/domain.py:21 orgs/serializers.py:13 +#: perms/serializers/permission.py:40 +msgid "Assets amount" +msgstr "" + +#: assets/serializers/gateway.py:23 common/validators.py:34 +msgid "This field must be unique." +msgstr "" + +#: assets/serializers/node.py:17 +msgid "value" +msgstr "" + +#: assets/serializers/node.py:31 +msgid "Can't contains: /" +msgstr "" + +#: assets/serializers/platform.py:33 +msgid "Enable asset detection" +msgstr "" + +#: assets/serializers/platform.py:37 +msgid "Enable asset information collection" +msgstr "" + +#: assets/serializers/platform.py:44 +msgid "Enable account verification" +msgstr "" + +#: assets/serializers/platform.py:51 +msgid "Enable account secret auto change" +msgstr "" + +#: assets/serializers/platform.py:58 +msgid "Enable account auto push" +msgstr "" + +#: assets/serializers/platform.py:64 +msgid "Gather accounts enabled" +msgstr "" + +#: assets/serializers/platform.py:65 +msgid "Enable account collection" +msgstr "" + +#: assets/serializers/platform.py:68 +msgid "Gather accounts method" +msgstr "" + +#: assets/serializers/platform.py:75 +msgid "Port from addr" +msgstr "" + +#: assets/serializers/platform.py:87 +msgid "" +"This protocol is primary, and it must be set when adding assets. " +"Additionally, there can only be one primary protocol." +msgstr "" + +#: assets/serializers/platform.py:92 +msgid "This protocol is required, and it must be set when adding assets." +msgstr "" + +#: assets/serializers/platform.py:95 +msgid "" +"This protocol is default, when adding assets, it will be displayed by " +"default." +msgstr "" + +#: assets/serializers/platform.py:98 +msgid "This protocol is public, asset will show this protocol to user" +msgstr "" + +#: assets/serializers/platform.py:147 +msgid "Help text" +msgstr "" + +#: assets/serializers/platform.py:148 +msgid "Choices" +msgstr "" + +#: assets/serializers/platform.py:167 +msgid "Automation" +msgstr "" + +#: assets/serializers/platform.py:193 +msgid "" +"Login with account when accessing assets, then automatically switch to " +"another, similar to logging in with a regular account and then switching to " +"root" +msgstr "" + +#: assets/serializers/platform.py:199 +msgid "Assets can be connected using a domain gateway" +msgstr "" + +#: assets/serializers/platform.py:201 +msgid "Default Domain" +msgstr "" + +#: assets/serializers/platform.py:222 +msgid "type is required" +msgstr "" + +#: assets/serializers/platform.py:237 +msgid "Protocols is required" +msgstr "" + +#: assets/signal_handlers/asset.py:26 assets/tasks/ping.py:35 +msgid "Test assets connectivity " +msgstr "" + +#: assets/signal_handlers/asset.py:36 +msgid "Gather asset hardware info" +msgstr "" + +#: assets/tasks/automation.py:24 +msgid "Asset execute automation" +msgstr "" + +#: assets/tasks/gather_facts.py:21 assets/tasks/gather_facts.py:27 +msgid "Gather assets facts" +msgstr "" + +#: assets/tasks/gather_facts.py:39 +msgid "Update assets hardware info: " +msgstr "" + +#: assets/tasks/gather_facts.py:47 +msgid "Update node asset hardware information: " +msgstr "" + +#: assets/tasks/nodes_amount.py:16 +msgid "Check the amount of assets under the node" +msgstr "" + +#: assets/tasks/nodes_amount.py:28 +msgid "" +"The task of self-checking is already running and cannot be started repeatedly" +msgstr "" + +#: assets/tasks/nodes_amount.py:33 +msgid "Periodic check the amount of assets under the node" +msgstr "" + +#: assets/tasks/ping.py:20 assets/tasks/ping.py:26 +msgid "Test assets connectivity" +msgstr "" + +#: assets/tasks/ping.py:42 +msgid "Test if the assets under the node are connectable " +msgstr "" + +#: assets/tasks/ping_gateway.py:19 assets/tasks/ping_gateway.py:25 +#: assets/tasks/ping_gateway.py:34 +msgid "Test gateways connectivity" +msgstr "" + +#: assets/tasks/utils.py:16 +msgid "Asset has been disabled, skipped: {}" +msgstr "" + +#: assets/tasks/utils.py:20 +msgid "Asset may not be support ansible, skipped: {}" +msgstr "" + +#: assets/tasks/utils.py:38 +msgid "For security, do not push user {}" +msgstr "" + +#: assets/tasks/utils.py:54 +msgid "No assets matched, stop task" +msgstr "" + +#: audits/apps.py:9 +msgid "App Audits" +msgstr "" + +#: audits/backends/db.py:16 +msgid "The text content is too long. Use Elasticsearch to store operation logs" +msgstr "" + +#: audits/backends/db.py:91 +msgid "Tips" +msgstr "" + +#: audits/const.py:12 +msgid "Mkdir" +msgstr "" + +#: audits/const.py:13 +msgid "Rmdir" +msgstr "" + +#: audits/const.py:14 audits/const.py:25 +#: authentication/templates/authentication/_access_key_modal.html:65 +#: rbac/tree.py:240 +msgid "Delete" +msgstr "" + +#: audits/const.py:15 +msgid "Upload" +msgstr "" + +#: audits/const.py:16 +msgid "Rename" +msgstr "" + +#: audits/const.py:17 +msgid "Symlink" +msgstr "" + +#: audits/const.py:18 audits/const.py:28 terminal/api/session/session.py:149 +msgid "Download" +msgstr "" + +#: audits/const.py:19 +msgid "Rename dir" +msgstr "" + +#: audits/const.py:23 rbac/tree.py:238 terminal/api/session/session.py:277 +#: terminal/templates/terminal/_msg_command_warning.html:18 +#: terminal/templates/terminal/_msg_session_sharing.html:10 +msgid "View" +msgstr "" + +#: audits/const.py:26 +#: authentication/templates/authentication/_access_key_modal.html:22 +#: rbac/tree.py:237 +msgid "Create" +msgstr "" + +#: audits/const.py:29 +msgid "Connect" +msgstr "" + +#: audits/const.py:30 authentication/templates/authentication/login.html:296 +#: authentication/templates/authentication/login.html:368 +#: templates/_header_bar.html:101 +msgid "Login" +msgstr "" + +#: audits/const.py:31 ops/const.py:9 +msgid "Change password" +msgstr "" + +#: audits/const.py:35 +msgid "Notifications" +msgstr "" + +#: audits/const.py:37 tickets/const.py:45 +msgid "Approve" +msgstr "" + +#: audits/const.py:38 +#: authentication/templates/authentication/_access_key_modal.html:155 +#: authentication/templates/authentication/_mfa_confirm_modal.html:53 +#: templates/_modal.html:22 tickets/const.py:43 +msgid "Close" +msgstr "" + +#: audits/const.py:43 settings/serializers/terminal.py:6 +#: terminal/models/applet/host.py:26 terminal/models/component/terminal.py:175 +#: terminal/models/virtualapp/provider.py:14 terminal/serializers/session.py:55 +#: terminal/serializers/session.py:69 +msgid "Terminal" +msgstr "" + +#: audits/const.py:48 audits/models.py:132 +msgid "Operate log" +msgstr "" + +#: audits/const.py:49 +msgid "Session log" +msgstr "" + +#: audits/const.py:50 +msgid "Login log" +msgstr "" + +#: audits/const.py:51 terminal/models/applet/host.py:144 +#: terminal/models/component/task.py:22 +msgid "Task" +msgstr "" + +#: audits/const.py:57 +msgid "-" +msgstr "" + +#: audits/handler.py:116 +msgid "Yes" +msgstr "" + +#: audits/handler.py:116 +msgid "No" +msgstr "" + +#: audits/models.py:47 +msgid "Job audit log" +msgstr "" + +#: audits/models.py:56 audits/models.py:100 audits/models.py:175 +#: terminal/models/session/session.py:39 terminal/models/session/sharing.py:113 +msgid "Remote addr" +msgstr "" + +#: audits/models.py:61 audits/serializers.py:38 +msgid "Operate" +msgstr "" + +#: audits/models.py:63 +msgid "Filename" +msgstr "" + +#: audits/models.py:66 common/serializers/common.py:98 +msgid "File" +msgstr "" + +#: audits/models.py:67 terminal/backends/command/models.py:21 +#: terminal/models/session/replay.py:9 terminal/models/session/sharing.py:20 +#: terminal/models/session/sharing.py:95 +#: terminal/templates/terminal/_msg_command_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:17 +#: tickets/models/ticket/command_confirm.py:15 +msgid "Session" +msgstr "" + +#: audits/models.py:70 +msgid "File transfer log" +msgstr "" + +#: audits/models.py:94 audits/serializers.py:86 +msgid "Resource Type" +msgstr "" + +#: audits/models.py:95 audits/models.py:98 audits/models.py:144 +#: audits/serializers.py:85 labels/serializers.py:46 +msgid "Resource" +msgstr "" + +#: audits/models.py:101 audits/models.py:147 audits/models.py:177 +#: terminal/serializers/command.py:75 +msgid "Datetime" +msgstr "" + +#: audits/models.py:140 +msgid "Activity type" +msgstr "" + +#: audits/models.py:150 +msgid "Detail" +msgstr "" + +#: audits/models.py:153 +msgid "Detail ID" +msgstr "" + +#: audits/models.py:157 +msgid "Activity log" +msgstr "" + +#: audits/models.py:173 +msgid "Change by" +msgstr "" + +#: audits/models.py:183 +msgid "Password change log" +msgstr "" + +#: audits/models.py:190 audits/models.py:265 +msgid "Login type" +msgstr "" + +#: audits/models.py:192 audits/models.py:261 +#: tickets/models/ticket/login_confirm.py:10 +msgid "Login IP" +msgstr "" + +#: audits/models.py:200 audits/serializers.py:52 +#: authentication/templates/authentication/_mfa_confirm_modal.html:14 +#: users/forms/profile.py:63 users/models/user.py:897 +#: users/serializers/profile.py:102 +msgid "MFA" +msgstr "" + +#: audits/models.py:210 +#: authentication/templates/authentication/_msg_different_city.html:10 +#: tickets/models/ticket/login_confirm.py:12 +msgid "Login Date" +msgstr "" + +#: audits/models.py:212 audits/models.py:266 +msgid "Auth backend" +msgstr "" + +#: audits/models.py:256 +msgid "User login log" +msgstr "" + +#: audits/models.py:262 +msgid "Session key" +msgstr "" + +#: audits/models.py:298 +msgid "User session" +msgstr "" + +#: audits/models.py:300 +msgid "Offline user session" +msgstr "" + +#: audits/serializers.py:33 ops/models/adhoc.py:25 ops/models/base.py:16 +#: ops/models/base.py:53 ops/models/celery.py:86 ops/models/job.py:151 +#: ops/models/job.py:239 ops/models/playbook.py:30 +#: terminal/models/session/sharing.py:25 +msgid "Creator" +msgstr "" + +#: audits/serializers.py:69 +msgid "Reason display" +msgstr "" + +#: audits/serializers.py:70 audits/serializers.py:184 +msgid "Auth backend display" +msgstr "" + +#: audits/serializers.py:134 +#, python-format +msgid "%s %s this resource" +msgstr "" + +#: audits/serializers.py:172 authentication/models/connection_token.py:47 +#: authentication/models/temp_token.py:13 perms/models/asset_permission.py:80 +#: tickets/models/ticket/apply_application.py:31 +#: tickets/models/ticket/apply_asset.py:20 users/models/user.py:915 +msgid "Date expired" +msgstr "" + +#: audits/signal_handlers/activity_log.py:26 +#, python-format +msgid "User %s use account %s login asset %s" +msgstr "" + +#: audits/signal_handlers/activity_log.py:34 +#, python-format +msgid "User %s login system %s" +msgstr "" + +#: audits/signal_handlers/activity_log.py:64 +#, python-format +msgid "User %s perform a task for this resource: %s" +msgstr "" + +#: audits/signal_handlers/login_log.py:33 +msgid "SSH Key" +msgstr "" + +#: audits/signal_handlers/login_log.py:35 settings/serializers/auth/sso.py:13 +msgid "SSO" +msgstr "" + +#: audits/signal_handlers/login_log.py:36 +msgid "Auth Token" +msgstr "" + +#: audits/signal_handlers/login_log.py:37 authentication/notifications.py:73 +#: authentication/views/login.py:77 notifications/backends/__init__.py:11 +#: settings/serializers/auth/wecom.py:10 settings/serializers/auth/wecom.py:15 +#: users/models/user.py:758 users/models/user.py:930 +msgid "WeCom" +msgstr "" + +#: audits/signal_handlers/login_log.py:38 authentication/views/feishu.py:105 +#: authentication/views/login.py:89 notifications/backends/__init__.py:14 +#: settings/serializers/auth/feishu.py:10 users/models/user.py:760 +#: users/models/user.py:932 +msgid "FeiShu" +msgstr "" + +#: audits/signal_handlers/login_log.py:40 authentication/views/login.py:101 +#: authentication/views/slack.py:87 notifications/backends/__init__.py:16 +#: settings/serializers/auth/slack.py:10 settings/serializers/auth/slack.py:12 +#: users/models/user.py:762 users/models/user.py:934 +msgid "Slack" +msgstr "" + +#: audits/signal_handlers/login_log.py:41 authentication/views/dingtalk.py:161 +#: authentication/views/login.py:83 notifications/backends/__init__.py:12 +#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:759 +#: users/models/user.py:931 +msgid "DingTalk" +msgstr "" + +#: audits/signal_handlers/login_log.py:42 +#: authentication/models/temp_token.py:16 +msgid "Temporary token" +msgstr "" + +#: audits/signal_handlers/login_log.py:43 authentication/views/login.py:107 +#: settings/serializers/auth/passkey.py:8 +#: settings/serializers/auth/passkey.py:11 +msgid "Passkey" +msgstr "" + +#: audits/tasks.py:117 +msgid "Clean audits session task log" +msgstr "" + +#: audits/tasks.py:130 +msgid "Upload FTP file to external storage" +msgstr "" + +#: authentication/api/access_key.py:39 +msgid "Access keys can be created at most 10" +msgstr "" + +#: authentication/api/common.py:34 settings/serializers/auth/sms.py:117 +#, python-format +msgid "The value in the parameter must contain %s" +msgstr "" + +#: authentication/api/confirm.py:50 +msgid "This action require verify your MFA" +msgstr "" + +#: authentication/api/connection_token.py:265 +msgid "Reusable connection token is not allowed, global setting not enabled" +msgstr "" + +#: authentication/api/connection_token.py:379 +msgid "Anonymous account is not supported for this asset" +msgstr "" + +#: authentication/api/connection_token.py:399 +msgid "Account not found" +msgstr "" + +#: authentication/api/connection_token.py:402 +msgid "Permission expired" +msgstr "" + +#: authentication/api/connection_token.py:435 +msgid "ACL action is reject: {}({})" +msgstr "" + +#: authentication/api/connection_token.py:439 +msgid "ACL action is review" +msgstr "" + +#: authentication/api/mfa.py:62 +msgid "Current user not support mfa type: {}" +msgstr "" + +#: authentication/api/password.py:33 terminal/api/session/session.py:325 +#: users/views/profile/reset.py:63 +msgid "User does not exist: {}" +msgstr "" + +#: authentication/api/password.py:33 users/views/profile/reset.py:166 +msgid "No user matched" +msgstr "" + +#: authentication/api/password.py:37 +msgid "" +"The user is from {}, please go to the corresponding system to change the " +"password" +msgstr "" + +#: authentication/api/password.py:65 +#: authentication/templates/authentication/login.html:360 +#: users/templates/users/forgot_password.html:41 +#: users/templates/users/forgot_password.html:42 +#: users/templates/users/forgot_password_previewing.html:13 +#: users/templates/users/forgot_password_previewing.html:14 +msgid "Forgot password" +msgstr "" + +#: authentication/apps.py:7 +msgid "App Authentication" +msgstr "" + +#: authentication/backends/custom.py:59 +#: authentication/backends/oauth2/backends.py:173 +msgid "User invalid, disabled or expired" +msgstr "" + +#: authentication/backends/drf.py:52 +msgid "Invalid token header. No credentials provided." +msgstr "" + +#: authentication/backends/drf.py:55 +msgid "Invalid token header. Sign string should not contain spaces." +msgstr "" + +#: authentication/backends/drf.py:61 +msgid "" +"Invalid token header. Sign string should not contain invalid characters." +msgstr "" + +#: authentication/backends/drf.py:74 +msgid "Invalid token or cache refreshed." +msgstr "" + +#: authentication/backends/passkey/api.py:37 +msgid "Only register passkey for local user" +msgstr "" + +#: authentication/backends/passkey/api.py:65 +msgid "Auth failed" +msgstr "" + +#: authentication/backends/passkey/fido.py:148 +msgid "This key is not registered" +msgstr "" + +#: authentication/backends/passkey/models.py:13 +msgid "Added on" +msgstr "" + +#: authentication/backends/passkey/models.py:14 +#: authentication/models/access_key.py:26 +#: authentication/models/private_token.py:8 +msgid "Date last used" +msgstr "" + +#: authentication/backends/passkey/models.py:15 +msgid "Credential ID" +msgstr "" + +#: authentication/confirm/password.py:16 +msgid "Authentication failed password incorrect" +msgstr "" + +#: authentication/confirm/relogin.py:10 +msgid "Login time has exceeded {} minutes, please login again" +msgstr "" + +#: authentication/errors/const.py:18 +msgid "Username/password check failed" +msgstr "" + +#: authentication/errors/const.py:19 +msgid "Password decrypt failed" +msgstr "" + +#: authentication/errors/const.py:20 +msgid "MFA failed" +msgstr "" + +#: authentication/errors/const.py:21 +msgid "MFA unset" +msgstr "" + +#: authentication/errors/const.py:22 +msgid "Username does not exist" +msgstr "" + +#: authentication/errors/const.py:23 +msgid "Password expired" +msgstr "" + +#: authentication/errors/const.py:24 +msgid "Disabled or expired" +msgstr "" + +#: authentication/errors/const.py:25 +msgid "This account is inactive." +msgstr "" + +#: authentication/errors/const.py:26 +msgid "This account is expired" +msgstr "" + +#: authentication/errors/const.py:27 +msgid "Auth backend not match" +msgstr "" + +#: authentication/errors/const.py:28 +msgid "ACL is not allowed" +msgstr "" + +#: authentication/errors/const.py:29 +msgid "Only local users are allowed" +msgstr "" + +#: authentication/errors/const.py:39 +msgid "No session found, check your cookie" +msgstr "" + +#: authentication/errors/const.py:41 +#, python-brace-format +msgid "" +"The username or password you entered is incorrect, please enter it again. " +"You can also try {times_try} times (The account will be temporarily locked " +"for {block_time} minutes)" +msgstr "" + +#: authentication/errors/const.py:47 authentication/errors/const.py:55 +msgid "" +"The account has been locked (please contact admin to unlock it or try again " +"after {} minutes)" +msgstr "" + +#: authentication/errors/const.py:51 +msgid "" +"The address has been locked (please contact admin to unlock it or try again " +"after {} minutes)" +msgstr "" + +#: authentication/errors/const.py:59 +#, python-brace-format +msgid "" +"{error}, You can also try {times_try} times (The account will be temporarily " +"locked for {block_time} minutes)" +msgstr "" + +#: authentication/errors/const.py:63 +msgid "MFA required" +msgstr "" + +#: authentication/errors/const.py:64 +msgid "MFA not set, please set it first" +msgstr "" + +#: authentication/errors/const.py:65 +msgid "Login confirm required" +msgstr "" + +#: authentication/errors/const.py:66 +msgid "Wait login confirm ticket for accept" +msgstr "" + +#: authentication/errors/const.py:67 +msgid "Login confirm ticket was {}" +msgstr "" + +#: authentication/errors/failed.py:149 +msgid "Current IP and Time period is not allowed" +msgstr "" + +#: authentication/errors/failed.py:154 +msgid "Please enter MFA code" +msgstr "" + +#: authentication/errors/failed.py:159 +msgid "Please enter SMS code" +msgstr "" + +#: authentication/errors/failed.py:164 users/exceptions.py:15 +msgid "Phone not set" +msgstr "" + +#: authentication/errors/mfa.py:8 +msgid "SSO auth closed" +msgstr "" + +#: authentication/errors/mfa.py:18 authentication/views/wecom.py:59 +msgid "WeCom is already bound" +msgstr "" + +#: authentication/errors/mfa.py:23 authentication/views/wecom.py:159 +#: authentication/views/wecom.py:201 +msgid "WeCom is not bound" +msgstr "" + +#: authentication/errors/mfa.py:28 authentication/views/dingtalk.py:213 +#: authentication/views/dingtalk.py:255 +msgid "DingTalk is not bound" +msgstr "" + +#: authentication/errors/mfa.py:33 authentication/views/feishu.py:138 +msgid "FeiShu is not bound" +msgstr "" + +#: authentication/errors/mfa.py:38 authentication/views/lark.py:48 +msgid "Lark is not bound" +msgstr "" + +#: authentication/errors/mfa.py:43 authentication/views/slack.py:127 +msgid "Slack is not bound" +msgstr "" + +#: authentication/errors/mfa.py:48 +msgid "Your password is invalid" +msgstr "" + +#: authentication/errors/mfa.py:53 +#, python-format +msgid "Please wait for %s seconds before retry" +msgstr "" + +#: authentication/errors/redirect.py:85 authentication/mixins.py:323 +msgid "Your password is too simple, please change it for security" +msgstr "" + +#: authentication/errors/redirect.py:93 authentication/mixins.py:330 +msgid "You should to change your password before login" +msgstr "" + +#: authentication/errors/redirect.py:101 authentication/mixins.py:337 +msgid "Your password has expired, please reset before logging in" +msgstr "" + +#: authentication/forms.py:39 +msgid "Auto login" +msgstr "" + +#: authentication/forms.py:52 +msgid "MFA Code" +msgstr "" + +#: authentication/forms.py:53 +msgid "MFA type" +msgstr "" + +#: authentication/forms.py:61 +#: authentication/templates/authentication/_captcha_field.html:15 +msgid "Captcha" +msgstr "" + +#: authentication/forms.py:66 users/forms/profile.py:27 +msgid "MFA code" +msgstr "" + +#: authentication/forms.py:68 +msgid "Dynamic code" +msgstr "" + +#: authentication/mfa/base.py:7 +msgid "Please input security code" +msgstr "" + +#: authentication/mfa/custom.py:20 +msgid "MFA Custom code invalid" +msgstr "" + +#: authentication/mfa/custom.py:26 +msgid "MFA custom verification code" +msgstr "" + +#: authentication/mfa/custom.py:56 +msgid "MFA custom global enabled, cannot disable" +msgstr "" + +#: authentication/mfa/otp.py:7 +msgid "OTP code invalid, or server time error" +msgstr "" + +#: authentication/mfa/otp.py:12 +msgid "OTP" +msgstr "" + +#: authentication/mfa/otp.py:13 +msgid "OTP verification code" +msgstr "" + +#: authentication/mfa/otp.py:48 +msgid "Virtual OTP based MFA" +msgstr "" + +#: authentication/mfa/radius.py:7 +msgid "Radius verify code invalid" +msgstr "" + +#: authentication/mfa/radius.py:13 +msgid "Radius verification code" +msgstr "" + +#: authentication/mfa/radius.py:44 +msgid "Radius global enabled, cannot disable" +msgstr "" + +#: authentication/mfa/sms.py:7 +msgid "SMS verify code invalid" +msgstr "" + +#: authentication/mfa/sms.py:12 authentication/serializers/password_mfa.py:16 +#: authentication/serializers/password_mfa.py:24 +#: settings/serializers/auth/sms.py:17 settings/serializers/auth/sms.py:32 +#: users/forms/profile.py:103 users/forms/profile.py:108 +#: users/templates/users/forgot_password.html:157 +#: users/views/profile/reset.py:100 +msgid "SMS" +msgstr "" + +#: authentication/mfa/sms.py:13 +msgid "SMS verification code" +msgstr "" + +#: authentication/mfa/sms.py:57 +msgid "Set phone number to enable" +msgstr "" + +#: authentication/mfa/sms.py:61 +msgid "Clear phone number to disable" +msgstr "" + +#: authentication/middleware.py:94 settings/utils/ldap.py:679 +msgid "Authentication failed (before login check failed): {}" +msgstr "" + +#: authentication/mixins.py:82 +msgid "User is invalid" +msgstr "" + +#: authentication/mixins.py:97 +msgid "" +"The administrator has enabled 'Only allow login from user source'. \n" +" The current user source is {}. Please contact the administrator." +msgstr "" + +#: authentication/mixins.py:273 +msgid "The MFA type ({}) is not enabled" +msgstr "" + +#: authentication/mixins.py:313 +msgid "Please change your password" +msgstr "" + +#: authentication/models/access_key.py:22 +#: terminal/models/component/endpoint.py:110 +msgid "IP group" +msgstr "" + +#: authentication/models/connection_token.py:38 +#: terminal/serializers/storage.py:114 +msgid "Account name" +msgstr "" + +#: authentication/models/connection_token.py:39 +msgid "Input username" +msgstr "" + +#: authentication/models/connection_token.py:40 +#: authentication/serializers/connection_token.py:18 +msgid "Input secret" +msgstr "" + +#: authentication/models/connection_token.py:41 +#: authentication/serializers/connect_token_secret.py:114 +#: settings/serializers/msg.py:29 terminal/models/applet/applet.py:42 +#: terminal/models/virtualapp/virtualapp.py:24 +#: terminal/serializers/session.py:21 terminal/serializers/session.py:48 +#: terminal/serializers/storage.py:71 +msgid "Protocol" +msgstr "" + +#: authentication/models/connection_token.py:42 +msgid "Connect method" +msgstr "" + +#: authentication/models/connection_token.py:43 +msgid "Connect options" +msgstr "" + +#: authentication/models/connection_token.py:44 +msgid "User display" +msgstr "" + +#: authentication/models/connection_token.py:45 +msgid "Asset display" +msgstr "" + +#: authentication/models/connection_token.py:46 +msgid "Reusable" +msgstr "" + +#: authentication/models/connection_token.py:51 +#: perms/models/asset_permission.py:83 +msgid "From ticket" +msgstr "" + +#: authentication/models/connection_token.py:58 +msgid "Can expire connection token" +msgstr "" + +#: authentication/models/connection_token.py:59 +msgid "Can reuse connection token" +msgstr "" + +#: authentication/models/connection_token.py:61 +msgid "Connection token" +msgstr "" + +#: authentication/models/connection_token.py:118 +msgid "Connection token inactive" +msgstr "" + +#: authentication/models/connection_token.py:122 +msgid "Connection token expired at: {}" +msgstr "" + +#: authentication/models/connection_token.py:125 +msgid "No user or invalid user" +msgstr "" + +#: authentication/models/connection_token.py:128 +msgid "No asset or inactive asset" +msgstr "" + +#: authentication/models/connection_token.py:274 +msgid "Can view super connection token secret" +msgstr "" + +#: authentication/models/connection_token.py:276 +msgid "Super connection token" +msgstr "" + +#: authentication/models/private_token.py:11 +msgid "Private Token" +msgstr "" + +#: authentication/models/sso_token.py:15 +msgid "Expired" +msgstr "" + +#: authentication/models/sso_token.py:20 +msgid "SSO token" +msgstr "" + +#: authentication/models/temp_token.py:11 +msgid "Verified" +msgstr "" + +#: authentication/notifications.py:19 +msgid "Different city login reminder" +msgstr "" + +#: authentication/notifications.py:52 +msgid "binding reminder" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:116 +msgid "Is builtin" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:120 +msgid "Options" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:127 +#: ops/notifications.py:18 +msgid "Component" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:138 +msgid "Expired now" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:170 +#: terminal/models/virtualapp/virtualapp.py:25 +msgid "Image name" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:171 +#: terminal/models/virtualapp/virtualapp.py:27 +msgid "Image port" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:172 +#: terminal/models/virtualapp/virtualapp.py:26 +msgid "Image protocol" +msgstr "" + +#: authentication/serializers/connection_token.py:16 +msgid "Expired time" +msgstr "" + +#: authentication/serializers/connection_token.py:20 +msgid "Ticket info" +msgstr "" + +#: authentication/serializers/connection_token.py:21 +#: perms/models/asset_permission.py:77 perms/serializers/permission.py:42 +#: perms/serializers/permission.py:64 +#: tickets/models/ticket/apply_application.py:28 +#: tickets/models/ticket/apply_asset.py:18 +msgid "Actions" +msgstr "" + +#: authentication/serializers/connection_token.py:42 +#: perms/serializers/permission.py:44 perms/serializers/permission.py:65 +#: users/serializers/user.py:101 users/serializers/user.py:184 +msgid "Is expired" +msgstr "" + +#: authentication/serializers/password_mfa.py:29 +#: users/templates/users/forgot_password.html:153 +msgid "The {} cannot be empty" +msgstr "" + +#: authentication/serializers/token.py:22 +msgid "Access IP" +msgstr "" + +#: authentication/serializers/token.py:92 perms/serializers/permission.py:43 +#: perms/serializers/permission.py:66 users/serializers/user.py:102 +#: users/serializers/user.py:181 +msgid "Is valid" +msgstr "" + +#: authentication/tasks.py:11 +msgid "Clean expired session" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:6 +msgid "API key list" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:18 +msgid "Using api key sign api header, every requests header difference" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:19 +msgid "docs" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:48 +msgid "Show" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:66 +#: users/const.py:42 users/models/user.py:654 users/serializers/profile.py:92 +#: users/templates/users/user_verify_mfa.html:36 +msgid "Disable" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:67 +#: users/const.py:43 users/models/user.py:655 users/serializers/profile.py:93 +#: users/templates/users/mfa_setting.html:26 +#: users/templates/users/mfa_setting.html:68 +msgid "Enable" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:147 +msgid "Delete success" +msgstr "" + +#: authentication/templates/authentication/_captcha_field.html:8 +msgid "Play CAPTCHA as audio file" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:5 +msgid "MFA confirm" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:17 +msgid "Need MFA for view auth" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:20 +#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:37 +#: templates/_modal.html:23 templates/flash_message_standalone.html:37 +#: users/templates/users/user_password_verify.html:20 +msgid "Confirm" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:25 +msgid "Code error" +msgstr "" + +#: authentication/templates/authentication/_msg_different_city.html:3 +#: authentication/templates/authentication/_msg_oauth_bind.html:3 +#: authentication/templates/authentication/_msg_reset_password.html:3 +#: 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:465 +#: 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:32 +#: users/templates/users/_msg_account_expire_reminder.html:4 +#: users/templates/users/_msg_password_expire_reminder.html:4 +#: users/templates/users/_msg_reset_mfa.html:4 +#: users/templates/users/_msg_reset_ssh_key.html:4 +msgid "Hello" +msgstr "" + +#: authentication/templates/authentication/_msg_different_city.html:6 +msgid "Your account has remote login behavior, please pay attention" +msgstr "" + +#: authentication/templates/authentication/_msg_different_city.html:16 +msgid "" +"If you suspect that the login behavior is abnormal, please modify the " +"account password in time." +msgstr "" + +#: authentication/templates/authentication/_msg_oauth_bind.html:6 +msgid "Your account has just been bound to" +msgstr "" + +#: authentication/templates/authentication/_msg_oauth_bind.html:17 +msgid "If the operation is not your own, unbind and change the password." +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:6 +msgid "" +"Please click the link below to reset your password, if not your request, " +"concern your account security" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:10 +msgid "Click here reset password" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:16 +#: users/templates/users/_msg_user_created.html:22 +msgid "This link is valid for 1 hour. After it expires" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:17 +#: users/templates/users/_msg_user_created.html:23 +msgid "request new one" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password_code.html:12 +#: terminal/models/session/sharing.py:27 terminal/models/session/sharing.py:97 +#: terminal/templates/terminal/_msg_session_sharing.html:12 +#: users/forms/profile.py:106 users/templates/users/forgot_password.html:98 +msgid "Verify code" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password_code.html:15 +msgid "" +"Copy the verification code to the Reset Password page to reset the password." +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password_code.html:18 +msgid "The validity period of the verification code is one minute" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:5 +msgid "Your password has just been successfully updated" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:9 +#: authentication/templates/authentication/_msg_rest_public_key_success.html:9 +msgid "Browser" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:13 +msgid "" +"If the password update was not initiated by you, your account may have " +"security issues" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:14 +#: authentication/templates/authentication/_msg_rest_public_key_success.html:14 +msgid "If you have any questions, you can contact the administrator" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_public_key_success.html:5 +msgid "Your public key has just been successfully updated" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_public_key_success.html:13 +msgid "" +"If the public key update was not initiated by you, your account may have " +"security issues" +msgstr "" + +#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:28 +#: templates/flash_message_standalone.html:28 tickets/const.py:18 +msgid "Cancel" +msgstr "" + +#: authentication/templates/authentication/login.html:276 +msgid "" +"Configuration file has problems and cannot be logged in. Please contact the " +"administrator or view latest docs" +msgstr "" + +#: authentication/templates/authentication/login.html:277 +msgid "If you are administrator, you can update the config resolve it, set" +msgstr "" + +#: authentication/templates/authentication/login.html:375 +msgid "More login options" +msgstr "" + +#: authentication/templates/authentication/login_mfa.html:6 +msgid "MFA Auth" +msgstr "" + +#: authentication/templates/authentication/login_mfa.html:19 +#: users/templates/users/user_otp_check_password.html:12 +#: users/templates/users/user_otp_enable_bind.html:24 +#: users/templates/users/user_otp_enable_install_app.html:31 +#: users/templates/users/user_verify_mfa.html:30 +msgid "Next" +msgstr "" + +#: authentication/templates/authentication/login_mfa.html:22 +msgid "Can't provide security? Please contact the administrator!" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:41 +msgid "Refresh" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:46 +msgid "Copy link" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:51 +msgid "Return" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:117 +msgid "Copy success" +msgstr "" + +#: authentication/templates/authentication/passkey.html:162 +msgid "" +"This page is not served over HTTPS. Please use HTTPS to ensure security of " +"your credentials." +msgstr "" + +#: authentication/templates/authentication/passkey.html:173 +msgid "Do you want to retry ?" +msgstr "" + +#: authentication/utils.py:24 common/utils/ip/geoip/utils.py:24 +#: xpack/plugins/cloud/const.py:32 +msgid "LAN" +msgstr "" + +#: authentication/views/base.py:73 +#: perms/templates/perms/_msg_permed_items_expire.html:21 +msgid "If you have any question, please contact the administrator" +msgstr "" + +#: authentication/views/base.py:146 +#, python-format +msgid "%s query user failed" +msgstr "" + +#: authentication/views/base.py:155 +#, python-format +msgid "The %s is already bound to another user" +msgstr "" + +#: authentication/views/base.py:162 +#, python-format +msgid "Binding %s successfully" +msgstr "" + +#: authentication/views/dingtalk.py:42 +msgid "DingTalk Error, Please contact your system administrator" +msgstr "" + +#: authentication/views/dingtalk.py:45 authentication/views/dingtalk.py:212 +msgid "DingTalk Error" +msgstr "" + +#: authentication/views/dingtalk.py:57 authentication/views/feishu.py:68 +#: authentication/views/slack.py:47 authentication/views/wecom.py:55 +msgid "" +"The system configuration is incorrect. Please contact your administrator" +msgstr "" + +#: authentication/views/dingtalk.py:61 +msgid "DingTalk is already bound" +msgstr "" + +#: authentication/views/dingtalk.py:130 +msgid "Invalid user_id" +msgstr "" + +#: authentication/views/dingtalk.py:146 +msgid "DingTalk query user failed" +msgstr "" + +#: authentication/views/dingtalk.py:155 +msgid "The DingTalk is already bound to another user" +msgstr "" + +#: authentication/views/dingtalk.py:162 +msgid "Binding DingTalk successfully" +msgstr "" + +#: authentication/views/dingtalk.py:214 authentication/views/dingtalk.py:249 +msgid "Failed to get user from DingTalk" +msgstr "" + +#: authentication/views/dingtalk.py:256 +msgid "Please login with a password and then bind the DingTalk" +msgstr "" + +#: authentication/views/feishu.py:43 authentication/views/feishu.py:137 +msgid "FeiShu Error" +msgstr "" + +#: authentication/views/feishu.py:44 +msgid "FeiShu is already bound" +msgstr "" + +#: authentication/views/feishu.py:139 +msgid "Failed to get user from FeiShu" +msgstr "" + +#: authentication/views/lark.py:19 authentication/views/lark.py:47 +msgid "Lark Error" +msgstr "" + +#: authentication/views/lark.py:20 +msgid "Lark is already bound" +msgstr "" + +#: authentication/views/lark.py:49 +msgid "Failed to get user from Lark" +msgstr "" + +#: authentication/views/login.py:230 +msgid "Redirecting" +msgstr "" + +#: authentication/views/login.py:231 +msgid "Redirecting to {} authentication" +msgstr "" + +#: authentication/views/login.py:254 +msgid "Login timeout, please try again." +msgstr "" + +#: authentication/views/login.py:297 +msgid "User email already exists ({})" +msgstr "" + +#: authentication/views/login.py:375 +msgid "" +"Wait for {} confirm, You also can copy link to her/him
\n" +" Don't close this page" +msgstr "" + +#: authentication/views/login.py:380 +msgid "No ticket found" +msgstr "" + +#: authentication/views/login.py:416 +msgid "Logout success" +msgstr "" + +#: authentication/views/login.py:417 +msgid "Logout success, return login page" +msgstr "" + +#: authentication/views/slack.py:35 authentication/views/slack.py:126 +msgid "Slack Error" +msgstr "" + +#: authentication/views/slack.py:63 +msgid "Slack is already bound" +msgstr "" + +#: authentication/views/slack.py:128 +msgid "Failed to get user from Slack" +msgstr "" + +#: authentication/views/wecom.py:40 +msgid "WeCom Error, Please contact your system administrator" +msgstr "" + +#: authentication/views/wecom.py:43 authentication/views/wecom.py:158 +msgid "WeCom Error" +msgstr "" + +#: authentication/views/wecom.py:118 +msgid "Wecom" +msgstr "" + +#: authentication/views/wecom.py:160 authentication/views/wecom.py:195 +msgid "Failed to get user from WeCom" +msgstr "" + +#: authentication/views/wecom.py:202 +msgid "Please login with a password and then bind the WeCom" +msgstr "" + +#: common/api/action.py:51 +msgid "Request file format may be wrong" +msgstr "" + +#: common/const/choices.py:10 +msgid "Manual trigger" +msgstr "" + +#: common/const/choices.py:11 +msgid "Timing trigger" +msgstr "" + +#: common/const/choices.py:15 +msgid "Ready" +msgstr "" + +#: common/const/choices.py:17 ops/const.py:73 +msgid "Running" +msgstr "" + +#: common/const/choices.py:21 +msgid "Canceled" +msgstr "" + +#: common/const/common.py:5 +#, python-format +msgid "%(name)s was created successfully" +msgstr "" + +#: common/const/common.py:6 +#, python-format +msgid "%(name)s was updated successfully" +msgstr "" + +#: common/db/encoder.py:11 +msgid "gettext_lazy" +msgstr "" + +#: common/db/fields.py:106 +msgid "Marshal dict data to char field" +msgstr "" + +#: common/db/fields.py:110 +msgid "Marshal dict data to text field" +msgstr "" + +#: common/db/fields.py:122 +msgid "Marshal list data to char field" +msgstr "" + +#: common/db/fields.py:126 +msgid "Marshal list data to text field" +msgstr "" + +#: common/db/fields.py:130 +msgid "Marshal data to char field" +msgstr "" + +#: common/db/fields.py:134 +msgid "Marshal data to text field" +msgstr "" + +#: common/db/fields.py:167 +msgid "Encrypt field using Secret Key" +msgstr "" + +#: common/db/fields.py:582 +msgid "" +"Invalid JSON data for JSONManyToManyField, should be like {'type': 'all'} or " +"{'type': 'ids', 'ids': []} or {'type': 'attrs', 'attrs': [{'name': 'ip', " +"'match': 'exact', 'value': '1.1.1.1'}}" +msgstr "" + +#: common/db/fields.py:589 +msgid "Invalid type, should be \"all\", \"ids\" or \"attrs\"" +msgstr "" + +#: common/db/fields.py:592 +msgid "Invalid ids for ids, should be a list" +msgstr "" + +#: common/db/fields.py:594 common/db/fields.py:599 +#: common/serializers/fields.py:133 tickets/serializers/ticket/common.py:58 +#: xpack/plugins/cloud/serializers/account_attrs.py:56 +#: xpack/plugins/cloud/serializers/account_attrs.py:79 +#: xpack/plugins/cloud/serializers/account_attrs.py:150 +msgid "This field is required." +msgstr "" + +#: common/db/fields.py:597 common/db/fields.py:602 +msgid "Invalid attrs, should be a list of dict" +msgstr "" + +#: common/db/fields.py:604 +msgid "Invalid attrs, should be has name and value" +msgstr "" + +#: common/db/mixins.py:32 +msgid "is discard" +msgstr "" + +#: common/db/mixins.py:33 +msgid "discard time" +msgstr "" + +#: common/db/models.py:33 users/models/user.py:918 +msgid "Updated by" +msgstr "" + +#: common/db/validators.py:9 +msgid "Invalid port range, should be like and within {}-{}" +msgstr "" + +#: common/drf/exc_handlers.py:26 +msgid "Object" +msgstr "" + +#: common/drf/metadata.py:127 +msgid "Org ID" +msgstr "" + +#: common/drf/parsers/base.py:21 +msgid "The file content overflowed (The maximum length `{}` bytes)" +msgstr "" + +#: common/drf/parsers/base.py:199 +msgid "Parse file error: {}" +msgstr "" + +#: common/drf/parsers/excel.py:14 +msgid "Invalid excel file" +msgstr "" + +#: common/drf/renders/base.py:208 +msgid "" +"{} - The encryption password has not been set - please go to personal " +"information -> file encryption password to set the encryption password" +msgstr "" + +#: common/exceptions.py:15 +#, python-format +msgid "%s object does not exist." +msgstr "" + +#: common/exceptions.py:25 +msgid "Someone else is doing this. Please wait for complete" +msgstr "" + +#: common/exceptions.py:30 +msgid "Your request timeout" +msgstr "" + +#: common/exceptions.py:35 +msgid "M2M reverse not allowed" +msgstr "" + +#: common/exceptions.py:41 +msgid "Is referenced by other objects and cannot be deleted" +msgstr "" + +#: common/exceptions.py:51 +msgid "This action require confirm current user" +msgstr "" + +#: common/exceptions.py:59 +msgid "Unexpect error occur" +msgstr "" + +#: common/plugins/es.py:31 +msgid "Invalid elasticsearch config" +msgstr "" + +#: common/plugins/es.py:36 +msgid "Not Support Elasticsearch8" +msgstr "" + +#: common/sdk/im/exceptions.py:23 +msgid "Network error, please contact system administrator" +msgstr "" + +#: common/sdk/im/slack/__init__.py:77 +msgid "Unknown error occur" +msgstr "" + +#: common/sdk/im/wecom/__init__.py:16 +msgid "WeCom error, please contact system administrator" +msgstr "" + +#: common/sdk/sms/alibaba.py:56 +msgid "Signature does not match" +msgstr "" + +#: common/sdk/sms/cmpp2.py:44 +msgid "sp_id is 6 bits" +msgstr "" + +#: common/sdk/sms/cmpp2.py:214 +msgid "Failed to connect to the CMPP gateway server, err: {}" +msgstr "" + +#: common/sdk/sms/custom_file.py:41 +msgid "The custom sms file is invalid" +msgstr "" + +#: common/sdk/sms/custom_file.py:47 +#, python-format +msgid "SMS sending failed[%s]: %s" +msgstr "" + +#: common/sdk/sms/endpoint.py:16 +msgid "Alibaba cloud" +msgstr "" + +#: common/sdk/sms/endpoint.py:17 +msgid "Tencent cloud" +msgstr "" + +#: common/sdk/sms/endpoint.py:18 xpack/plugins/cloud/const.py:13 +msgid "Huawei Cloud" +msgstr "" + +#: common/sdk/sms/endpoint.py:19 +msgid "CMPP v2.0" +msgstr "" + +#: common/sdk/sms/endpoint.py:21 +msgid "Custom type (File)" +msgstr "" + +#: common/sdk/sms/endpoint.py:32 +msgid "SMS provider not support: {}" +msgstr "" + +#: common/sdk/sms/endpoint.py:54 +msgid "SMS verification code signature or template invalid" +msgstr "" + +#: common/sdk/sms/exceptions.py:8 +msgid "The verification code has expired. Please resend it" +msgstr "" + +#: common/sdk/sms/exceptions.py:13 +msgid "The verification code is incorrect" +msgstr "" + +#: common/sdk/sms/exceptions.py:18 +msgid "Please wait {} seconds before sending" +msgstr "" + +#: common/serializers/common.py:90 +msgid "Children" +msgstr "" + +#: common/serializers/fields.py:134 +#, python-brace-format +msgid "Invalid pk \"{pk_value}\" - object does not exist." +msgstr "" + +#: common/serializers/fields.py:135 +#, python-brace-format +msgid "Incorrect type. Expected pk value, received {data_type}." +msgstr "" + +#: common/serializers/fields.py:209 +msgid "Invalid data type, should be list" +msgstr "" + +#: common/serializers/fields.py:224 +msgid "Invalid choice: {}" +msgstr "" + +#: common/serializers/mixin.py:409 +msgid "Labels" +msgstr "" + +#: common/tasks.py:31 common/utils/verify_code.py:16 +msgid "Send email" +msgstr "" + +#: common/tasks.py:58 +msgid "Send email attachment" +msgstr "" + +#: common/tasks.py:80 terminal/tasks.py:58 +msgid "Upload session replay to external storage" +msgstr "" + +#: common/utils/ip/geoip/utils.py:26 +msgid "Invalid ip" +msgstr "" + +#: common/utils/ip/utils.py:98 +msgid "Invalid address" +msgstr "" + +#: common/utils/translate.py:45 +#, python-format +msgid "Hello %s" +msgstr "" + +#: common/validators.py:16 +msgid "Special char not allowed" +msgstr "" + +#: common/validators.py:42 +msgid "Should not contains special characters" +msgstr "" + +#: common/validators.py:47 +msgid "The mobile phone number format is incorrect" +msgstr "" + +#: jumpserver/conf.py:459 +#, python-brace-format +msgid "The verification code is: {code}" +msgstr "" + +#: jumpserver/conf.py:464 +msgid "Create account successfully" +msgstr "" + +#: jumpserver/conf.py:466 +msgid "Your account has been created successfully" +msgstr "" + +#: jumpserver/context_processor.py:14 +msgid "JumpServer Open Source Bastion Host" +msgstr "" + +#: jumpserver/views/celery_flower.py:22 +msgid "

Flower service unavailable, check it

" +msgstr "" + +#: jumpserver/views/other.py:27 +msgid "" +"
Luna is a separately deployed program, you need to deploy Luna, koko, " +"configure nginx for url distribution,
If you see this page, " +"prove that you are not accessing the nginx listening port. Good luck." +msgstr "" + +#: jumpserver/views/other.py:72 +msgid "Websocket server run on port: {}, you should proxy it on nginx" +msgstr "" + +#: jumpserver/views/other.py:86 +msgid "" +"
Koko is a separately deployed program, you need to deploy Koko, " +"configure nginx for url distribution,
If you see this page, " +"prove that you are not accessing the nginx listening port. Good luck." +msgstr "" + +#: labels/apps.py:8 +msgid "App Labels" +msgstr "" + +#: labels/models.py:36 +msgid "Resource ID" +msgstr "" + +#: labels/models.py:41 +msgid "Labeled resource" +msgstr "" + +#: labels/serializers.py:22 +msgid "Resource count" +msgstr "" + +#: labels/serializers.py:28 +msgid "Cannot contain \":,\"" +msgstr "" + +#: labels/serializers.py:43 +msgid "Resource type" +msgstr "" + +#: notifications/apps.py:7 +msgid "App Notifications" +msgstr "" + +#: notifications/backends/__init__.py:13 +msgid "Site message" +msgstr "" + +#: notifications/models/notification.py:14 +msgid "receive backend" +msgstr "" + +#: notifications/models/notification.py:18 +msgid "User message" +msgstr "" + +#: notifications/models/notification.py:21 +msgid "{} subscription" +msgstr "" + +#: notifications/models/notification.py:34 +msgid "System message" +msgstr "" + +#: notifications/notifications.py:46 +msgid "Publish the station message" +msgstr "" + +#: ops/ansible/inventory.py:107 ops/models/job.py:65 +msgid "No account available" +msgstr "" + +#: ops/ansible/inventory.py:286 +msgid "Ansible disabled" +msgstr "" + +#: ops/ansible/inventory.py:302 +msgid "Skip hosts below:" +msgstr "" + +#: ops/api/celery.py:66 ops/api/celery.py:81 +msgid "Waiting task start" +msgstr "" + +#: ops/api/celery.py:262 +msgid "Task {} not found" +msgstr "" + +#: ops/api/celery.py:267 +msgid "Task {} args or kwargs error" +msgstr "" + +#: ops/api/job.py:81 +#, python-brace-format +msgid "" +"Asset ({asset}) must have at least one of the following protocols added: " +"SSH, SFTP, or WinRM" +msgstr "" + +#: ops/api/job.py:82 +#, python-brace-format +msgid "Asset ({asset}) authorization is missing SSH, SFTP, or WinRM protocol" +msgstr "" + +#: ops/api/job.py:83 +#, python-brace-format +msgid "Asset ({asset}) authorization lacks upload permissions" +msgstr "" + +#: ops/api/job.py:168 +msgid "Duplicate file exists" +msgstr "" + +#: ops/api/job.py:173 +#, python-brace-format +msgid "" +"File size exceeds maximum limit. Please select a file smaller than {limit}MB" +msgstr "" + +#: ops/api/job.py:237 +msgid "" +"The task is being created and cannot be interrupted. Please try again later." +msgstr "" + +#: ops/api/playbook.py:39 +msgid "Currently playbook is being used in a job" +msgstr "" + +#: ops/api/playbook.py:96 +msgid "Unsupported file content" +msgstr "" + +#: ops/api/playbook.py:98 ops/api/playbook.py:144 ops/api/playbook.py:192 +msgid "Invalid file path" +msgstr "" + +#: ops/api/playbook.py:170 +msgid "This file can not be rename" +msgstr "" + +#: ops/api/playbook.py:189 +msgid "File already exists" +msgstr "" + +#: ops/api/playbook.py:207 +msgid "File key is required" +msgstr "" + +#: ops/api/playbook.py:210 +msgid "This file can not be delete" +msgstr "" + +#: ops/apps.py:9 +msgid "App Ops" +msgstr "" + +#: ops/const.py:6 +msgid "Push" +msgstr "" + +#: ops/const.py:7 +msgid "Verify" +msgstr "" + +#: ops/const.py:8 +msgid "Collect" +msgstr "" + +#: ops/const.py:19 +msgid "Custom password" +msgstr "" + +#: ops/const.py:20 +msgid "All assets use the same random password" +msgstr "" + +#: ops/const.py:21 +msgid "All assets use different random password" +msgstr "" + +#: ops/const.py:33 +msgid "Blank" +msgstr "" + +#: ops/const.py:34 +msgid "VCS" +msgstr "" + +#: ops/const.py:38 ops/models/adhoc.py:44 +msgid "Adhoc" +msgstr "" + +#: ops/const.py:39 ops/models/job.py:149 +msgid "Playbook" +msgstr "" + +#: ops/const.py:40 +msgid "Upload File" +msgstr "" + +#: ops/const.py:44 +msgid "Privileged Only" +msgstr "" + +#: ops/const.py:45 +msgid "Privileged First" +msgstr "" + +#: ops/const.py:50 ops/const.py:61 +msgid "Shell" +msgstr "" + +#: ops/const.py:51 ops/const.py:62 +msgid "Powershell" +msgstr "" + +#: ops/const.py:52 ops/const.py:63 +msgid "Python" +msgstr "" + +#: ops/const.py:53 ops/const.py:64 +msgid "MySQL" +msgstr "" + +#: ops/const.py:54 ops/const.py:66 +msgid "PostgreSQL" +msgstr "" + +#: ops/const.py:55 ops/const.py:67 +msgid "SQLServer" +msgstr "" + +#: ops/const.py:56 ops/const.py:69 +msgid "Raw" +msgstr "" + +#: ops/const.py:57 +msgid "HUAWEI" +msgstr "" + +#: ops/const.py:65 +msgid "MariaDB" +msgstr "" + +#: ops/const.py:68 +msgid "Oracle" +msgstr "" + +#: ops/const.py:75 +msgid "Timeout" +msgstr "" + +#: ops/exception.py:6 +msgid "no valid program entry found." +msgstr "" + +#: ops/mixin.py:23 ops/mixin.py:102 settings/serializers/auth/ldap.py:66 +msgid "Periodic run" +msgstr "" + +#: ops/mixin.py:25 ops/mixin.py:88 ops/mixin.py:108 +#: settings/serializers/auth/ldap.py:73 +msgid "Interval" +msgstr "" + +#: ops/mixin.py:28 ops/mixin.py:86 ops/mixin.py:105 +#: settings/serializers/auth/ldap.py:70 +msgid "Crontab" +msgstr "" + +#: ops/mixin.py:110 +msgid "Run period" +msgstr "" + +#: ops/mixin.py:119 +msgid "* Please enter a valid crontab expression" +msgstr "" + +#: ops/mixin.py:126 +msgid "Range {} to {}" +msgstr "" + +#: ops/mixin.py:137 +msgid "Require interval or crontab setting" +msgstr "" + +#: ops/models/adhoc.py:21 +msgid "Pattern" +msgstr "" + +#: ops/models/adhoc.py:23 ops/models/job.py:146 +msgid "Module" +msgstr "" + +#: ops/models/adhoc.py:24 ops/models/celery.py:81 ops/models/job.py:144 +#: terminal/models/component/task.py:14 +msgid "Args" +msgstr "" + +#: ops/models/base.py:19 +msgid "Account policy" +msgstr "" + +#: ops/models/base.py:20 +msgid "Last execution" +msgstr "" + +#: ops/models/base.py:22 ops/serializers/job.py:17 +msgid "Date last run" +msgstr "" + +#: ops/models/base.py:51 ops/models/job.py:237 +#: xpack/plugins/cloud/models.py:202 +msgid "Result" +msgstr "" + +#: ops/models/base.py:52 ops/models/job.py:238 +msgid "Summary" +msgstr "" + +#: ops/models/celery.py:16 +msgid "Date last publish" +msgstr "" + +#: ops/models/celery.py:70 +msgid "Celery Task" +msgstr "" + +#: ops/models/celery.py:73 +msgid "Can view task monitor" +msgstr "" + +#: ops/models/celery.py:82 terminal/models/component/task.py:15 +msgid "Kwargs" +msgstr "" + +#: ops/models/celery.py:84 terminal/models/session/sharing.py:128 +#: tickets/const.py:25 +msgid "Finished" +msgstr "" + +#: ops/models/celery.py:87 +msgid "Date published" +msgstr "" + +#: ops/models/celery.py:112 +msgid "Celery Task Execution" +msgstr "" + +#: ops/models/job.py:147 +msgid "Chdir" +msgstr "" + +#: ops/models/job.py:148 +msgid "Timeout (Seconds)" +msgstr "" + +#: ops/models/job.py:153 +msgid "Use Parameter Define" +msgstr "" + +#: ops/models/job.py:154 +msgid "Parameters define" +msgstr "" + +#: ops/models/job.py:155 +msgid "Runas" +msgstr "" + +#: ops/models/job.py:157 +msgid "Runas policy" +msgstr "" + +#: ops/models/job.py:221 terminal/notifications.py:174 +msgid "Job" +msgstr "" + +#: ops/models/job.py:244 +msgid "Material" +msgstr "" + +#: ops/models/job.py:246 +msgid "Material Type" +msgstr "" + +#: ops/models/job.py:544 +msgid "Job Execution" +msgstr "" + +#: ops/models/playbook.py:33 +msgid "CreateMethod" +msgstr "" + +#: ops/models/playbook.py:34 +msgid "VCS URL" +msgstr "" + +#: ops/notifications.py:19 +msgid "Server performance" +msgstr "" + +#: ops/notifications.py:25 +msgid "Terminal health check warning" +msgstr "" + +#: ops/notifications.py:70 +#, python-brace-format +msgid "The terminal is offline: {name}" +msgstr "" + +#: ops/notifications.py:75 +#, python-brace-format +msgid "Disk used more than {max_threshold}%: => {value}" +msgstr "" + +#: ops/notifications.py:80 +#, python-brace-format +msgid "Memory used more than {max_threshold}%: => {value}" +msgstr "" + +#: ops/notifications.py:85 +#, python-brace-format +msgid "CPU load more than {max_threshold}: => {value}" +msgstr "" + +#: ops/serializers/celery.py:33 +msgid "Execution cycle" +msgstr "" + +#: ops/serializers/celery.py:35 +msgid "Next execution time" +msgstr "" + +#: ops/serializers/job.py:15 +msgid "Execute after saving" +msgstr "" + +#: ops/serializers/job.py:52 +msgid "Average time cost" +msgstr "" + +#: ops/serializers/job.py:72 +msgid "Job type" +msgstr "" + +#: ops/serializers/job.py:75 terminal/serializers/session.py:56 +msgid "Is finished" +msgstr "" + +#: ops/serializers/job.py:76 +#: settings/templates/ldap/_msg_import_ldap_user.html:7 +msgid "Time cost" +msgstr "" + +#: ops/serializers/job.py:90 +msgid "You do not have permission for the current job." +msgstr "" + +#: ops/tasks.py:38 +msgid "Run ansible task" +msgstr "" + +#: ops/tasks.py:72 +msgid "Run ansible task execution" +msgstr "" + +#: ops/tasks.py:94 +msgid "Clear celery periodic tasks" +msgstr "" + +#: ops/tasks.py:115 +msgid "Create or update periodic tasks" +msgstr "" + +#: ops/tasks.py:123 +msgid "Periodic check service performance" +msgstr "" + +#: ops/tasks.py:129 +msgid "Clean up unexpected jobs" +msgstr "" + +#: ops/tasks.py:136 +msgid "Clean job_execution db record" +msgstr "" + +#: ops/templates/ops/celery_task_log.html:4 +msgid "Task log" +msgstr "" + +#: ops/variables.py:24 +msgid "The current user`s username of JumpServer" +msgstr "" + +#: ops/variables.py:25 +msgid "The id of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:26 +msgid "The type of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:27 +msgid "The category of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:28 +msgid "The name of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:29 +msgid "Address used to connect this asset in JumpServer" +msgstr "" + +#: ops/variables.py:30 +msgid "Port used to connect this asset in JumpServer" +msgstr "" + +#: ops/variables.py:31 +msgid "ID of the job" +msgstr "" + +#: ops/variables.py:32 +msgid "Name of the job" +msgstr "" + +#: orgs/api.py:61 +msgid "The current organization ({}) cannot be deleted" +msgstr "" + +#: orgs/api.py:66 +msgid "" +"LDAP synchronization is set to the current organization. Please switch to " +"another organization before deleting" +msgstr "" + +#: orgs/api.py:76 +msgid "The organization have resource ({}) cannot be deleted" +msgstr "" + +#: orgs/apps.py:7 +msgid "App Organizations" +msgstr "" + +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:91 +#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/serializers/rolebinding.py:44 settings/serializers/auth/ldap.py:63 +#: terminal/templates/terminal/_msg_command_warning.html:21 +#: terminal/templates/terminal/_msg_session_sharing.html:14 +#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:60 +msgid "Organization" +msgstr "" + +#: orgs/mixins/serializers.py:26 rbac/serializers/rolebinding.py:27 +msgid "Org name" +msgstr "" + +#: orgs/models.py:14 +msgid "GLOBAL" +msgstr "" + +#: orgs/models.py:16 +msgid "DEFAULT" +msgstr "" + +#: orgs/models.py:18 +msgid "SYSTEM" +msgstr "" + +#: orgs/models.py:83 rbac/models/role.py:36 settings/models.py:185 +#: terminal/models/applet/applet.py:41 +msgid "Builtin" +msgstr "" + +#: orgs/models.py:93 +msgid "Can view root org" +msgstr "" + +#: orgs/models.py:94 +msgid "Can view all joined org" +msgstr "" + +#: orgs/models.py:236 +msgid "Can not delete virtual org" +msgstr "" + +#: orgs/serializers.py:10 perms/serializers/permission.py:38 +#: rbac/serializers/role.py:27 users/serializers/group.py:54 +msgid "Users amount" +msgstr "" + +#: orgs/serializers.py:11 +msgid "User groups amount" +msgstr "" + +#: orgs/serializers.py:14 perms/serializers/permission.py:41 +msgid "Nodes amount" +msgstr "" + +#: orgs/serializers.py:15 +msgid "Domains amount" +msgstr "" + +#: orgs/serializers.py:16 +msgid "Gateways amount" +msgstr "" + +#: orgs/serializers.py:18 +msgid "Asset permissions amount" +msgstr "" + +#: orgs/tasks.py:9 +msgid "Refresh organization cache" +msgstr "" + +#: perms/apps.py:9 +msgid "App Permissions" +msgstr "" + +#: perms/const.py:12 +msgid "Connect (All protocols)" +msgstr "" + +#: perms/const.py:13 +msgid "Upload (RDP, SFTP)" +msgstr "" + +#: perms/const.py:14 +msgid "Download (RDP, SFTP)" +msgstr "" + +#: perms/const.py:15 +msgid "Copy (RDP, VNC)" +msgstr "" + +#: perms/const.py:16 +msgid "Paste (RDP, VNC)" +msgstr "" + +#: perms/const.py:17 +msgid "Delete (SFTP)" +msgstr "" + +#: perms/const.py:18 +msgid "Share (SSH)" +msgstr "" + +#: perms/const.py:28 +msgid "Transfer" +msgstr "" + +#: perms/const.py:29 +msgid "Clipboard" +msgstr "" + +#: perms/models/asset_permission.py:89 +msgid "Asset permission" +msgstr "" + +#: perms/models/perm_node.py:68 +msgid "Ungrouped" +msgstr "" + +#: perms/models/perm_node.py:70 +msgid "Favorite" +msgstr "" + +#: perms/models/perm_node.py:121 +msgid "Permed asset" +msgstr "" + +#: perms/models/perm_node.py:123 +msgid "Can view my assets" +msgstr "" + +#: perms/models/perm_node.py:124 +msgid "Can view user assets" +msgstr "" + +#: perms/models/perm_node.py:125 +msgid "Can view usergroup assets" +msgstr "" + +#: perms/models/perm_node.py:136 +msgid "Permed account" +msgstr "" + +#: perms/notifications.py:12 perms/notifications.py:44 +msgid "today" +msgstr "" + +#: perms/notifications.py:12 perms/notifications.py:44 +#: settings/serializers/feature.py:118 +msgid "day" +msgstr "" + +#: perms/notifications.py:15 +msgid "You permed assets is about to expire" +msgstr "" + +#: perms/notifications.py:20 +msgid "permed assets" +msgstr "" + +#: perms/notifications.py:59 +msgid "Asset permissions is about to expire" +msgstr "" + +#: perms/notifications.py:64 +msgid "asset permissions of organization {}" +msgstr "" + +#: perms/serializers/permission.py:34 users/serializers/user.py:173 +msgid "Groups" +msgstr "" + +#: perms/serializers/permission.py:39 +msgid "Groups amount" +msgstr "" + +#: perms/tasks.py:27 +msgid "Check asset permission expired" +msgstr "" + +#: perms/tasks.py:40 +msgid "Send asset permission expired notification" +msgstr "" + +#: perms/templates/perms/_msg_item_permissions_expire.html:7 +#: perms/templates/perms/_msg_permed_items_expire.html:7 +#, python-format +msgid "" +"\n" +" The following %(item_type)s will expire in %(count)s\n" +" " +msgstr "" + +#: rbac/api/role.py:35 +msgid "Internal role, can't be destroy" +msgstr "" + +#: rbac/api/role.py:40 +msgid "The role has been bound to users, can't be destroy" +msgstr "" + +#: rbac/api/role.py:105 +msgid "Internal role, can't be update" +msgstr "" + +#: rbac/api/rolebinding.py:45 +msgid "{} at least one system role" +msgstr "" + +#: rbac/apps.py:7 +msgid "App RBAC" +msgstr "" + +#: rbac/builtin.py:115 +msgid "SystemAdmin" +msgstr "" + +#: rbac/builtin.py:118 +msgid "SystemAuditor" +msgstr "" + +#: rbac/builtin.py:121 +msgid "SystemComponent" +msgstr "" + +#: rbac/builtin.py:127 +msgid "OrgAdmin" +msgstr "" + +#: rbac/builtin.py:130 +msgid "OrgAuditor" +msgstr "" + +#: rbac/builtin.py:133 +msgid "OrgUser" +msgstr "" + +#: rbac/models/menu.py:13 +msgid "Menu permission" +msgstr "" + +#: rbac/models/menu.py:15 +msgid "Can view console view" +msgstr "" + +#: rbac/models/menu.py:16 +msgid "Can view audit view" +msgstr "" + +#: rbac/models/menu.py:17 +msgid "Can view workbench view" +msgstr "" + +#: rbac/models/menu.py:18 +msgid "Can view web terminal" +msgstr "" + +#: rbac/models/menu.py:19 +msgid "Can view file manager" +msgstr "" + +#: rbac/models/menu.py:20 +msgid "Can view System Tools" +msgstr "" + +#: rbac/models/permission.py:78 rbac/models/role.py:34 +msgid "Permissions" +msgstr "" + +#: rbac/models/role.py:31 rbac/models/rolebinding.py:46 +#: rbac/serializers/role.py:12 settings/serializers/auth/oauth2.py:36 +msgid "Scope" +msgstr "" + +#: rbac/models/role.py:46 rbac/models/rolebinding.py:52 +#: users/models/user.py:884 +msgid "Role" +msgstr "" + +#: rbac/models/role.py:144 +msgid "System role" +msgstr "" + +#: rbac/models/role.py:152 +msgid "Organization role" +msgstr "" + +#: rbac/models/rolebinding.py:62 +msgid "Role binding" +msgstr "" + +#: rbac/models/rolebinding.py:161 +msgid "All organizations" +msgstr "" + +#: rbac/models/rolebinding.py:193 +msgid "" +"User last role in org, can not be delete, you can remove user from org " +"instead" +msgstr "" + +#: rbac/models/rolebinding.py:200 +msgid "Organization role binding" +msgstr "" + +#: rbac/models/rolebinding.py:215 +msgid "System role binding" +msgstr "" + +#: rbac/serializers/permission.py:25 users/serializers/profile.py:108 +msgid "Perms" +msgstr "" + +#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:34 +#: terminal/models/virtualapp/virtualapp.py:20 +msgid "Display name" +msgstr "" + +#: rbac/serializers/rolebinding.py:60 +msgid "Has bound this role" +msgstr "" + +#: rbac/tree.py:17 rbac/tree.py:18 +msgid "All permissions" +msgstr "" + +#: rbac/tree.py:24 +msgid "Console view" +msgstr "" + +#: rbac/tree.py:25 +msgid "Workbench view" +msgstr "" + +#: rbac/tree.py:26 +msgid "Audit view" +msgstr "" + +#: rbac/tree.py:27 settings/models.py:161 +msgid "System setting" +msgstr "" + +#: rbac/tree.py:37 +msgid "Session audits" +msgstr "" + +#: rbac/tree.py:49 +msgid "Cloud import" +msgstr "" + +#: rbac/tree.py:50 +msgid "Backup account" +msgstr "" + +#: rbac/tree.py:51 +msgid "Gather account" +msgstr "" + +#: rbac/tree.py:53 +msgid "Asset change auth" +msgstr "" + +#: rbac/tree.py:54 +msgid "Terminal setting" +msgstr "" + +#: rbac/tree.py:55 settings/serializers/feature.py:127 +msgid "Job center" +msgstr "" + +#: rbac/tree.py:56 +msgid "My assets" +msgstr "" + +#: rbac/tree.py:57 +msgid "App ops" +msgstr "" + +#: rbac/tree.py:58 terminal/models/applet/applet.py:52 +#: terminal/models/applet/applet.py:317 terminal/models/applet/host.py:30 +#: terminal/serializers/applet.py:15 +msgid "Applet" +msgstr "" + +#: rbac/tree.py:128 +msgid "App organizations" +msgstr "" + +#: rbac/tree.py:129 +msgid "Ticket comment" +msgstr "" + +#: rbac/tree.py:130 settings/serializers/feature.py:109 +#: tickets/models/ticket/general.py:305 +msgid "Ticket" +msgstr "" + +#: rbac/tree.py:131 +msgid "Common setting" +msgstr "" + +#: rbac/tree.py:132 +msgid "View permission tree" +msgstr "" + +#: settings/api/chat.py:40 +msgid "Chat AI is not enabled" +msgstr "" + +#: settings/api/chat.py:79 settings/api/dingtalk.py:31 +#: settings/api/feishu.py:36 settings/api/slack.py:34 settings/api/sms.py:160 +#: settings/api/vault.py:40 settings/api/wecom.py:37 +msgid "Test success" +msgstr "" + +#: settings/api/email.py:22 +msgid "Test mail sent to {}, please check" +msgstr "" + +#: settings/api/ldap.py:89 +msgid "" +"Users are not synchronized, please click the user synchronization button" +msgstr "" + +#: settings/api/sms.py:142 +msgid "Invalid SMS platform" +msgstr "" + +#: settings/api/sms.py:148 +msgid "test_phone is required" +msgstr "" + +#: settings/apps.py:7 +msgid "App Settings" +msgstr "" + +#: settings/models.py:37 users/models/preference.py:14 +msgid "Encrypted" +msgstr "" + +#: settings/models.py:163 +msgid "Can change email setting" +msgstr "" + +#: settings/models.py:164 +msgid "Can change auth setting" +msgstr "" + +#: settings/models.py:165 +msgid "Can change auth ops" +msgstr "" + +#: settings/models.py:166 +msgid "Can change auth ticket" +msgstr "" + +#: settings/models.py:167 +msgid "Can change virtual app setting" +msgstr "" + +#: settings/models.py:168 +msgid "Can change auth announcement" +msgstr "" + +#: settings/models.py:169 +msgid "Can change vault setting" +msgstr "" + +#: settings/models.py:170 +msgid "Can change chat ai setting" +msgstr "" + +#: settings/models.py:171 +msgid "Can change system msg sub setting" +msgstr "" + +#: settings/models.py:172 +msgid "Can change sms setting" +msgstr "" + +#: settings/models.py:173 +msgid "Can change security setting" +msgstr "" + +#: settings/models.py:174 +msgid "Can change clean setting" +msgstr "" + +#: settings/models.py:175 +msgid "Can change interface setting" +msgstr "" + +#: settings/models.py:176 +msgid "Can change license setting" +msgstr "" + +#: settings/models.py:177 +msgid "Can change terminal setting" +msgstr "" + +#: settings/models.py:178 +msgid "Can change other setting" +msgstr "" + +#: settings/models.py:188 +msgid "Chat prompt" +msgstr "" + +#: settings/notifications.py:23 +msgid "Notification of Synchronized LDAP User Task Results" +msgstr "" + +#: settings/serializers/auth/base.py:10 +msgid "Authentication" +msgstr "" + +#: settings/serializers/auth/base.py:12 +msgid "LDAP Auth" +msgstr "" + +#: settings/serializers/auth/base.py:13 +msgid "CAS Auth" +msgstr "" + +#: settings/serializers/auth/base.py:14 +msgid "OPENID Auth" +msgstr "" + +#: settings/serializers/auth/base.py:15 +msgid "SAML2 Auth" +msgstr "" + +#: settings/serializers/auth/base.py:16 +msgid "OAuth2 Auth" +msgstr "" + +#: settings/serializers/auth/base.py:17 +msgid "RADIUS Auth" +msgstr "" + +#: settings/serializers/auth/base.py:18 +msgid "DingTalk Auth" +msgstr "" + +#: settings/serializers/auth/base.py:19 +msgid "FeiShu Auth" +msgstr "" + +#: settings/serializers/auth/base.py:20 +msgid "Lark Auth" +msgstr "" + +#: settings/serializers/auth/base.py:21 +msgid "Slack Auth" +msgstr "" + +#: settings/serializers/auth/base.py:22 +msgid "WeCom Auth" +msgstr "" + +#: settings/serializers/auth/base.py:23 +msgid "SSO Auth" +msgstr "" + +#: settings/serializers/auth/base.py:24 +msgid "Passkey Auth" +msgstr "" + +#: settings/serializers/auth/base.py:27 +msgid "Forgot Password URL" +msgstr "" + +#: settings/serializers/auth/base.py:30 +msgid "Login redirection prompt" +msgstr "" + +#: settings/serializers/auth/cas.py:10 settings/serializers/auth/cas.py:12 +msgid "CAS" +msgstr "" + +#: settings/serializers/auth/cas.py:13 settings/serializers/auth/ldap.py:42 +#: settings/serializers/auth/oidc.py:54 +msgid "Server" +msgstr "" + +#: settings/serializers/auth/cas.py:16 +msgid "Proxy Server" +msgstr "" + +#: settings/serializers/auth/cas.py:18 settings/serializers/auth/oauth2.py:54 +#: settings/serializers/auth/saml2.py:33 +msgid "Logout completely" +msgstr "" + +#: settings/serializers/auth/cas.py:23 +msgid "Username attr" +msgstr "" + +#: settings/serializers/auth/cas.py:26 +msgid "Enable attributes map" +msgstr "" + +#: settings/serializers/auth/cas.py:28 settings/serializers/auth/ldap.py:58 +#: settings/serializers/auth/oauth2.py:56 settings/serializers/auth/oidc.py:37 +#: settings/serializers/auth/saml2.py:32 +msgid "User attribute" +msgstr "" + +#: settings/serializers/auth/cas.py:30 +msgid "Create user" +msgstr "" + +#: settings/serializers/auth/cas.py:31 +msgid "Automatically create a new user if not found." +msgstr "" + +#: settings/serializers/auth/dingtalk.py:15 +msgid "Dingtalk" +msgstr "" + +#: settings/serializers/auth/feishu.py:12 +msgid "Enable FeiShu Auth" +msgstr "" + +#: settings/serializers/auth/lark.py:12 +msgid "Enable Lark Auth" +msgstr "" + +#: settings/serializers/auth/ldap.py:39 settings/serializers/auth/ldap.py:93 +msgid "LDAP" +msgstr "" + +#: settings/serializers/auth/ldap.py:43 +msgid "eg: ldap://localhost:389" +msgstr "" + +#: settings/serializers/auth/ldap.py:45 +msgid "Bind DN" +msgstr "" + +#: settings/serializers/auth/ldap.py:50 +msgid "User OU" +msgstr "" + +#: settings/serializers/auth/ldap.py:51 +msgid "Use | split multi OUs" +msgstr "" + +#: settings/serializers/auth/ldap.py:54 +msgid "User search filter" +msgstr "" + +#: settings/serializers/auth/ldap.py:55 +#, python-format +msgid "Choice may be (cn|uid|sAMAccountName)=%(user)s)" +msgstr "" + +#: settings/serializers/auth/ldap.py:59 +msgid "" +"User attr map present how to map LDAP user attr to jumpserver, username,name," +"email is jumpserver attr" +msgstr "" + +#: settings/serializers/auth/ldap.py:77 +msgid "Connect timeout (s)" +msgstr "" + +#: settings/serializers/auth/ldap.py:82 +msgid "User DN cache timeout (s)" +msgstr "" + +#: settings/serializers/auth/ldap.py:84 +msgid "" +"Caching the User DN obtained during user login authentication can " +"effectivelyimprove the speed of user authentication., 0 means no cache" +msgstr "" + +#: settings/serializers/auth/ldap.py:88 +msgid "Search paged size (piece)" +msgstr "" + +#: settings/serializers/auth/oauth2.py:18 +#: settings/serializers/auth/oauth2.py:21 +msgid "OAuth2" +msgstr "" + +#: settings/serializers/auth/oauth2.py:24 +msgid "Logo" +msgstr "" + +#: settings/serializers/auth/oauth2.py:27 +msgid "Service provider" +msgstr "" + +#: settings/serializers/auth/oauth2.py:30 settings/serializers/auth/oidc.py:19 +msgid "Client Id" +msgstr "" + +#: settings/serializers/auth/oauth2.py:33 settings/serializers/auth/oidc.py:22 +#: xpack/plugins/cloud/serializers/account_attrs.py:38 +msgid "Client Secret" +msgstr "" + +#: settings/serializers/auth/oauth2.py:39 settings/serializers/auth/oidc.py:68 +msgid "Authorization endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:42 settings/serializers/auth/oidc.py:71 +msgid "Token endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:45 settings/serializers/auth/oidc.py:30 +#: settings/serializers/auth/sms.py:106 +msgid "Request method" +msgstr "" + +#: settings/serializers/auth/oauth2.py:49 settings/serializers/auth/oidc.py:77 +msgid "Userinfo endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:52 settings/serializers/auth/oidc.py:80 +msgid "End session endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:59 settings/serializers/auth/oidc.py:98 +#: settings/serializers/auth/saml2.py:34 +msgid "Always update user" +msgstr "" + +#: settings/serializers/auth/oidc.py:12 settings/serializers/auth/oidc.py:63 +msgid "OIDC" +msgstr "" + +#: settings/serializers/auth/oidc.py:16 +msgid "Base site URL" +msgstr "" + +#: settings/serializers/auth/oidc.py:32 +msgid "Share session" +msgstr "" + +#: settings/serializers/auth/oidc.py:34 +msgid "Ignore SSL verification" +msgstr "" + +#: settings/serializers/auth/oidc.py:38 +msgid "" +"User attr map present how to map OpenID user attr to jumpserver, username," +"name,email is jumpserver attr" +msgstr "" + +#: settings/serializers/auth/oidc.py:41 +msgid "Enable PKCE" +msgstr "" + +#: settings/serializers/auth/oidc.py:43 +msgid "Code challenge method" +msgstr "" + +#: settings/serializers/auth/oidc.py:51 +msgid "Use Keycloak" +msgstr "" + +#: settings/serializers/auth/oidc.py:57 +msgid "Realm name" +msgstr "" + +#: settings/serializers/auth/oidc.py:65 +msgid "Provider endpoint" +msgstr "" + +#: settings/serializers/auth/oidc.py:74 +msgid "JWKS endpoint" +msgstr "" + +#: settings/serializers/auth/oidc.py:83 +msgid "Signature algorithm" +msgstr "" + +#: settings/serializers/auth/oidc.py:86 +msgid "Signing key" +msgstr "" + +#: settings/serializers/auth/oidc.py:88 +msgid "Scopes" +msgstr "" + +#: settings/serializers/auth/oidc.py:90 +msgid "ID Token max age (s)" +msgstr "" + +#: settings/serializers/auth/oidc.py:93 +msgid "ID Token include claims" +msgstr "" + +#: settings/serializers/auth/oidc.py:95 +msgid "Use state" +msgstr "" + +#: settings/serializers/auth/oidc.py:96 +msgid "Use nonce" +msgstr "" + +#: settings/serializers/auth/passkey.py:12 +msgid "Only SSL domain can use passkey auth" +msgstr "" + +#: settings/serializers/auth/passkey.py:15 +msgid "FIDO Server ID" +msgstr "" + +#: settings/serializers/auth/passkey.py:17 +msgid "" +"The hostname can using passkey auth, If not set, will use request host and " +"the request host in DOMAINS, If multiple domains, use comma to separate" +msgstr "" + +#: settings/serializers/auth/passkey.py:22 +msgid "FIDO Server name" +msgstr "" + +#: settings/serializers/auth/radius.py:13 +#: settings/serializers/auth/radius.py:15 +msgid "Radius" +msgstr "" + +#: settings/serializers/auth/radius.py:21 +msgid "OTP in Radius" +msgstr "" + +#: settings/serializers/auth/saml2.py:10 settings/serializers/auth/saml2.py:13 +msgid "SAML2" +msgstr "" + +#: settings/serializers/auth/saml2.py:16 +msgid "IDP Metadata URL" +msgstr "" + +#: settings/serializers/auth/saml2.py:19 +msgid "IDP Metadata XML" +msgstr "" + +#: settings/serializers/auth/saml2.py:22 +msgid "SP advanced settings" +msgstr "" + +#: settings/serializers/auth/saml2.py:26 +msgid "SP private key" +msgstr "" + +#: settings/serializers/auth/saml2.py:30 +msgid "SP cert" +msgstr "" + +#: settings/serializers/auth/sms.py:19 +msgid "SMS provider / Protocol" +msgstr "" + +#: settings/serializers/auth/sms.py:22 +msgid "SMS code length" +msgstr "" + +#: settings/serializers/auth/sms.py:27 settings/serializers/auth/sms.py:49 +#: settings/serializers/auth/sms.py:57 settings/serializers/auth/sms.py:66 +#: settings/serializers/auth/sms.py:77 settings/serializers/msg.py:83 +msgid "Signature" +msgstr "" + +#: settings/serializers/auth/sms.py:28 settings/serializers/auth/sms.py:50 +#: settings/serializers/auth/sms.py:58 settings/serializers/auth/sms.py:67 +msgid "Template code" +msgstr "" + +#: settings/serializers/auth/sms.py:35 +msgid "Test phone" +msgstr "" + +#: settings/serializers/auth/sms.py:64 +msgid "App Access Address" +msgstr "" + +#: settings/serializers/auth/sms.py:65 +msgid "Signature channel number" +msgstr "" + +#: settings/serializers/auth/sms.py:73 +msgid "Enterprise code" +msgstr "" + +#: settings/serializers/auth/sms.py:74 +msgid "Shared secret" +msgstr "" + +#: settings/serializers/auth/sms.py:75 +msgid "Original number" +msgstr "" + +#: settings/serializers/auth/sms.py:76 +msgid "Business type" +msgstr "" + +#: settings/serializers/auth/sms.py:80 +#, python-brace-format +msgid "" +"Template need contain {code} and Signature + template length does not exceed " +"67 words. For example, your verification code is {code}, which is valid for " +"5 minutes. Please do not disclose it to others." +msgstr "" + +#: settings/serializers/auth/sms.py:89 +#, python-brace-format +msgid "The template needs to contain {code}" +msgstr "" + +#: settings/serializers/auth/sms.py:92 +msgid "Signature + Template must not exceed 65 words" +msgstr "" + +#: settings/serializers/auth/sms.py:101 +msgid "URL" +msgstr "" + +#: settings/serializers/auth/sso.py:16 +msgid "Enable SSO auth" +msgstr "" + +#: settings/serializers/auth/sso.py:17 +msgid "Other service can using SSO token login to JumpServer without password" +msgstr "" + +#: settings/serializers/auth/sso.py:20 +msgid "SSO auth key TTL" +msgstr "" + +#: settings/serializers/auth/sso.py:20 +#: xpack/plugins/cloud/serializers/account_attrs.py:200 +msgid "Unit: second" +msgstr "" + +#: settings/serializers/basic.py:11 +msgid "Site URL" +msgstr "" + +#: settings/serializers/basic.py:13 +msgid "" +"External URL, email links or other system callbacks are used to access it, " +"eg: http://dev.jumpserver.org:8080" +msgstr "" + +#: settings/serializers/basic.py:18 +msgid "User guide url" +msgstr "" + +#: settings/serializers/basic.py:19 +msgid "User first login update profile done redirect to it" +msgstr "" + +#: settings/serializers/basic.py:22 +msgid "Global organization" +msgstr "" + +#: settings/serializers/basic.py:23 +msgid "The name of global organization to display" +msgstr "" + +#: settings/serializers/basic.py:26 +msgid "Help Docs URL" +msgstr "" + +#: settings/serializers/basic.py:27 +msgid "default: http://docs.jumpserver.org" +msgstr "" + +#: settings/serializers/basic.py:30 +msgid "Help Support URL" +msgstr "" + +#: settings/serializers/basic.py:31 +msgid "default: http://www.jumpserver.org/support/" +msgstr "" + +#: settings/serializers/basic.py:44 +msgid "Organization name already exists" +msgstr "" + +#: settings/serializers/cleaning.py:11 +msgid "Period clean" +msgstr "" + +#: settings/serializers/cleaning.py:15 +msgid "Login log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:19 +msgid "Task log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:23 +msgid "Operate log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:27 +msgid "password change log keep days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:31 +msgid "FTP log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:35 +msgid "Cloud sync task history retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:39 +msgid "job execution retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:43 +msgid "Activity log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:46 +msgid "Session log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:48 +msgid "" +"Session, record, command will be delete if more than duration, only in " +"database, OSS will not be affected." +msgstr "" + +#: settings/serializers/feature.py:18 settings/serializers/msg.py:68 +msgid "Subject" +msgstr "" + +#: settings/serializers/feature.py:22 +msgid "More URL" +msgstr "" + +#: settings/serializers/feature.py:36 settings/serializers/feature.py:38 +#: settings/serializers/feature.py:39 +msgid "Announcement" +msgstr "" + +#: settings/serializers/feature.py:46 +msgid "Vault" +msgstr "" + +#: settings/serializers/feature.py:55 +msgid "Mount Point" +msgstr "" + +#: settings/serializers/feature.py:60 +msgid "Historical accounts retained count" +msgstr "" + +#: settings/serializers/feature.py:62 +msgid "" +"If the specific value is less than 999, the system will automatically " +"perform a task every night: check and delete historical accounts that exceed " +"the predetermined number. If the value reaches or exceeds 999, no historical " +"account deletion will be performed." +msgstr "" + +#: settings/serializers/feature.py:71 settings/serializers/feature.py:75 +msgid "Chat AI" +msgstr "" + +#: settings/serializers/feature.py:78 +msgid "Base Url" +msgstr "" + +#: settings/serializers/feature.py:81 templates/_header_bar.html:96 +msgid "API Key" +msgstr "" + +#: settings/serializers/feature.py:87 +msgid "GPT Model" +msgstr "" + +#: settings/serializers/feature.py:111 +msgid "Enable tickets" +msgstr "" + +#: settings/serializers/feature.py:112 +msgid "No login approval" +msgstr "" + +#: settings/serializers/feature.py:115 +msgid "Default period" +msgstr "" + +#: settings/serializers/feature.py:118 +msgid "hour" +msgstr "" + +#: settings/serializers/feature.py:119 +msgid "Default unit" +msgstr "" + +#: settings/serializers/feature.py:124 +msgid "Feature" +msgstr "" + +#: settings/serializers/feature.py:128 +msgid "Allow user run batch command or not using ansible" +msgstr "" + +#: settings/serializers/feature.py:132 +msgid "Command blacklist" +msgstr "" + +#: settings/serializers/feature.py:133 +msgid "Commands that are not allowed execute." +msgstr "" + +#: settings/serializers/feature.py:138 settings/serializers/feature.py:141 +#: terminal/models/virtualapp/provider.py:17 +#: terminal/models/virtualapp/virtualapp.py:36 +#: terminal/models/virtualapp/virtualapp.py:97 +#: terminal/serializers/virtualapp.py:32 +msgid "Virtual app" +msgstr "" + +#: settings/serializers/msg.py:25 +msgid "SMTP" +msgstr "" + +#: settings/serializers/msg.py:26 +msgid "EXCHANGE" +msgstr "" + +#: settings/serializers/msg.py:36 +msgid "Tips: Some provider use token except password" +msgstr "" + +#: settings/serializers/msg.py:39 +msgid "Sender" +msgstr "" + +#: settings/serializers/msg.py:40 +msgid "Tips: Send mail account, default SMTP account as the send account" +msgstr "" + +#: settings/serializers/msg.py:43 +msgid "Test recipient" +msgstr "" + +#: settings/serializers/msg.py:44 +msgid "Tips: Used only as a test mail recipient" +msgstr "" + +#: settings/serializers/msg.py:48 +msgid "If SMTP port is 465, may be select" +msgstr "" + +#: settings/serializers/msg.py:51 +msgid "Use TLS" +msgstr "" + +#: settings/serializers/msg.py:52 +msgid "If SMTP port is 587, may be select" +msgstr "" + +#: settings/serializers/msg.py:55 +msgid "Subject prefix" +msgstr "" + +#: settings/serializers/msg.py:58 +msgid "Email suffix" +msgstr "" + +#: settings/serializers/msg.py:59 +msgid "" +"This is used by default if no email is returned during SSO authentication" +msgstr "" + +#: settings/serializers/msg.py:69 +msgid "" +"Tips: When creating a user, send the subject of the email (eg:Create account " +"successfully)" +msgstr "" + +#: settings/serializers/msg.py:73 +msgid "Honorific" +msgstr "" + +#: settings/serializers/msg.py:74 +msgid "Tips: When creating a user, send the honorific of the email (eg:Hello)" +msgstr "" + +#: settings/serializers/msg.py:80 +#, python-brace-format +msgid "" +"Tips: When creating a user, send the content of the email, support " +"{username} {name} {email} label" +msgstr "" + +#: settings/serializers/msg.py:84 +msgid "Tips: Email signature (eg:jumpserver)" +msgstr "" + +#: settings/serializers/other.py:8 +msgid "More..." +msgstr "" + +#: settings/serializers/other.py:11 +msgid "Perm ungroup node" +msgstr "" + +#: settings/serializers/other.py:12 +msgid "Perm single to ungroup node" +msgstr "" + +#: settings/serializers/security.py:17 +msgid "User password expiration (day)" +msgstr "" + +#: settings/serializers/security.py:19 +msgid "" +"If the user does not update the password during the time, the user password " +"will expire failure;The password expiration reminder mail will be automatic " +"sent to the user by system within 5 days (daily) before the password expires" +msgstr "" + +#: settings/serializers/security.py:26 +msgid "Recent password count" +msgstr "" + +#: settings/serializers/security.py:28 +msgid "" +"Tip: When the user resets the password, it cannot be the previous n " +"historical passwords of the user" +msgstr "" + +#: settings/serializers/security.py:34 +msgid "Minimum length (User)" +msgstr "" + +#: settings/serializers/security.py:38 +msgid "Minimum length (Admin)" +msgstr "" + +#: settings/serializers/security.py:47 +msgid "Digits" +msgstr "" + +#: settings/serializers/security.py:50 +msgid "Special characters" +msgstr "" + +#: settings/serializers/security.py:55 +msgid "" +"If the user has failed to log in for a limited number of times, no login is " +"allowed during this time interval." +msgstr "" + +#: settings/serializers/security.py:63 settings/serializers/security.py:73 +msgid "Login failures count" +msgstr "" + +#: settings/serializers/security.py:67 settings/serializers/security.py:77 +msgid "Login failure period (minute)" +msgstr "" + +#: settings/serializers/security.py:81 +msgid "Login IP whitelist" +msgstr "" + +#: settings/serializers/security.py:86 +msgid "Login IP blacklist" +msgstr "" + +#: settings/serializers/security.py:91 +msgid "Only single device login" +msgstr "" + +#: settings/serializers/security.py:92 +msgid "" +"After the user logs in on the new device, other logged-in devices will " +"automatically log out" +msgstr "" + +#: settings/serializers/security.py:95 +msgid "Only exist user login" +msgstr "" + +#: settings/serializers/security.py:97 +msgid "" +"If enabled, non-existent users will not be allowed to log in; if disabled, " +"users of other authentication methods except local authentication methods " +"are allowed to log in and automatically create users (if the user does not " +"exist)" +msgstr "" + +#: settings/serializers/security.py:103 +msgid "Only from source login" +msgstr "" + +#: settings/serializers/security.py:105 +msgid "" +"If it is enabled, the user will only authenticate to the source when logging " +"in; if it is disabled, the user will authenticate all the enabled " +"authentication methods in a certain order when logging in, and as long as " +"one of the authentication methods is successful, they can log in directly" +msgstr "" + +#: settings/serializers/security.py:116 +msgid "Not enabled" +msgstr "" + +#: settings/serializers/security.py:117 +msgid "All users" +msgstr "" + +#: settings/serializers/security.py:118 +msgid "Only admin users" +msgstr "" + +#: settings/serializers/security.py:120 +msgid "Global MFA auth" +msgstr "" + +#: settings/serializers/security.py:124 +msgid "Third-party login MFA" +msgstr "" + +#: settings/serializers/security.py:125 +msgid "The third-party login modes include OIDC, CAS, and SAML2" +msgstr "" + +#: settings/serializers/security.py:128 +msgid "OTP issuer name" +msgstr "" + +#: settings/serializers/security.py:132 +msgid "OTP valid window" +msgstr "" + +#: settings/serializers/security.py:136 +msgid "MFA verify TTL" +msgstr "" + +#: settings/serializers/security.py:138 +msgid "" +"Unit: second, The verification MFA takes effect only when you view the " +"account password" +msgstr "" + +#: settings/serializers/security.py:143 +msgid "MFA in login page" +msgstr "" + +#: settings/serializers/security.py:144 +msgid "Eu security regulations(GDPR) require MFA to be on the login page" +msgstr "" + +#: settings/serializers/security.py:148 +msgid "Verify code TTL (second)" +msgstr "" + +#: settings/serializers/security.py:149 +msgid "Reset password and send SMS code expiration time" +msgstr "" + +#: settings/serializers/security.py:153 +msgid "Login dynamic code" +msgstr "" + +#: settings/serializers/security.py:154 +msgid "" +"The password and additional code are sent to a third party authentication " +"system for verification" +msgstr "" + +#: settings/serializers/security.py:158 +msgid "Login captcha" +msgstr "" + +#: settings/serializers/security.py:159 +msgid "Enable captcha to prevent robot authentication" +msgstr "" + +#: settings/serializers/security.py:162 +msgid "Suspicious Login Verification" +msgstr "" + +#: settings/serializers/security.py:164 +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 " +"a remote login reminder" +msgstr "" + +#: settings/serializers/security.py:170 +msgid "Auto Disable Threshold (day)" +msgstr "" + +#: settings/serializers/security.py:171 +msgid "" +"Detect infrequent users daily and disable them if they exceed the " +"predetermined time limit." +msgstr "" + +#: settings/serializers/security.py:191 +msgid "Watermark" +msgstr "" + +#: settings/serializers/security.py:192 +msgid "Enabled, the web session and replay contains watermark information" +msgstr "" + +#: settings/serializers/security.py:196 +msgid "Max idle time (minute)" +msgstr "" + +#: settings/serializers/security.py:197 +msgid "If idle time more than it, disconnect connection." +msgstr "" + +#: settings/serializers/security.py:200 +msgid "Session expire at browser closed" +msgstr "" + +#: settings/serializers/security.py:201 +msgid "Whether to expire the session when the user closes their browser." +msgstr "" + +#: settings/serializers/security.py:205 +msgid "Max online time (hour)" +msgstr "" + +#: settings/serializers/security.py:206 +msgid "If session connection time more than it, disconnect connection." +msgstr "" + +#: settings/serializers/security.py:209 +msgid "Remember manual auth" +msgstr "" + +#: settings/serializers/security.py:212 +#: terminal/templates/terminal/_msg_session_sharing.html:10 +msgid "Session share" +msgstr "" + +#: settings/serializers/security.py:213 +msgid "Enabled, Allows user active session to be shared with other users" +msgstr "" + +#: settings/serializers/security.py:219 +msgid "Insecure command alert" +msgstr "" + +#: settings/serializers/security.py:222 +msgid "Email recipient" +msgstr "" + +#: settings/serializers/security.py:223 +msgid "Multiple user using , split" +msgstr "" + +#: settings/serializers/settings.py:62 +#, python-format +msgid "[%s] %s" +msgstr "" + +#: settings/serializers/terminal.py:15 +msgid "Auto" +msgstr "" + +#: settings/serializers/terminal.py:22 +msgid "Terminal registration" +msgstr "" + +#: settings/serializers/terminal.py:24 +msgid "" +"Allow terminal register, after all terminal setup, you should disable this " +"for security" +msgstr "" + +#: settings/serializers/terminal.py:27 +msgid "Password auth" +msgstr "" + +#: settings/serializers/terminal.py:29 +msgid "Public key auth" +msgstr "" + +#: settings/serializers/terminal.py:30 +msgid "" +"Information: If use other auth method, like AD/LDAP, you should disable this " +"to avoid being able to log in after deleting" +msgstr "" + +#: settings/serializers/terminal.py:34 +msgid "Asset list sorting" +msgstr "" + +#: settings/serializers/terminal.py:37 +msgid "Asset list page size" +msgstr "" + +#: settings/tasks/ldap.py:28 +msgid "Periodic import ldap user" +msgstr "" + +#: settings/tasks/ldap.py:66 +msgid "Registration periodic import ldap user task" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:2 +msgid "Sync task Finish" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:6 +#: terminal/models/session/session.py:46 +msgid "Date end" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:9 +msgid "Synced Organization" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:15 +msgid "Synced User" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:22 +msgid "No user synchronization required" +msgstr "" + +#: settings/utils/ldap.py:494 +msgid "ldap:// or ldaps:// protocol is used." +msgstr "" + +#: settings/utils/ldap.py:505 +msgid "Host or port is disconnected: {}" +msgstr "" + +#: settings/utils/ldap.py:507 +msgid "The port is not the port of the LDAP service: {}" +msgstr "" + +#: settings/utils/ldap.py:509 +msgid "Please add certificate: {}" +msgstr "" + +#: settings/utils/ldap.py:513 settings/utils/ldap.py:540 +#: settings/utils/ldap.py:570 settings/utils/ldap.py:598 +msgid "Unknown error: {}" +msgstr "" + +#: settings/utils/ldap.py:527 +msgid "Bind DN or Password incorrect" +msgstr "" + +#: settings/utils/ldap.py:534 +msgid "Please enter Bind DN: {}" +msgstr "" + +#: settings/utils/ldap.py:536 +msgid "Please enter Password: {}" +msgstr "" + +#: settings/utils/ldap.py:538 +msgid "Please enter correct Bind DN and Password: {}" +msgstr "" + +#: settings/utils/ldap.py:556 +msgid "Invalid User OU or User search filter: {}" +msgstr "" + +#: settings/utils/ldap.py:587 +msgid "LDAP User attr map not include: {}" +msgstr "" + +#: settings/utils/ldap.py:594 +msgid "LDAP User attr map is not dict" +msgstr "" + +#: settings/utils/ldap.py:613 +msgid "LDAP authentication is not enabled" +msgstr "" + +#: settings/utils/ldap.py:631 +msgid "Error (Invalid LDAP server): {}" +msgstr "" + +#: settings/utils/ldap.py:633 +msgid "Error (Invalid Bind DN): {}" +msgstr "" + +#: settings/utils/ldap.py:635 +msgid "Error (Invalid LDAP User attr map): {}" +msgstr "" + +#: settings/utils/ldap.py:637 +msgid "Error (Invalid User OU or User search filter): {}" +msgstr "" + +#: settings/utils/ldap.py:639 +msgid "Error (Not enabled LDAP authentication): {}" +msgstr "" + +#: settings/utils/ldap.py:641 +msgid "Error (Unknown): {}" +msgstr "" + +#: settings/utils/ldap.py:644 +msgid "Succeed: Match {} s user" +msgstr "" + +#: settings/utils/ldap.py:677 +msgid "Authentication failed (configuration incorrect): {}" +msgstr "" + +#: settings/utils/ldap.py:681 +msgid "Authentication failed (username or password incorrect): {}" +msgstr "" + +#: settings/utils/ldap.py:683 +msgid "Authentication failed (Unknown): {}" +msgstr "" + +#: settings/utils/ldap.py:686 +msgid "Authentication success: {}" +msgstr "" + +#: settings/ws.py:195 +msgid "Get ldap users is None" +msgstr "" + +#: settings/ws.py:205 +msgid "Imported {} users successfully (Organization: {})" +msgstr "" + +#: templates/_csv_import_export.html:8 +msgid "Export" +msgstr "" + +#: templates/_csv_import_export.html:13 templates/_csv_import_modal.html:5 +msgid "Import" +msgstr "" + +#: templates/_csv_import_modal.html:12 +msgid "Download the imported template or use the exported CSV file format" +msgstr "" + +#: templates/_csv_import_modal.html:13 +msgid "Download the import template" +msgstr "" + +#: templates/_csv_import_modal.html:17 templates/_csv_update_modal.html:17 +msgid "Select the CSV file to import" +msgstr "" + +#: templates/_csv_import_modal.html:39 templates/_csv_update_modal.html:42 +msgid "Please select file" +msgstr "" + +#: templates/_csv_update_modal.html:12 +msgid "Download the update template or use the exported CSV file format" +msgstr "" + +#: templates/_csv_update_modal.html:13 +msgid "Download the update template" +msgstr "" + +#: templates/_header_bar.html:12 +msgid "Help" +msgstr "" + +#: templates/_header_bar.html:19 +msgid "Docs" +msgstr "" + +#: templates/_header_bar.html:27 +msgid "Commercial support" +msgstr "" + +#: templates/_header_bar.html:85 users/forms/profile.py:43 +msgid "Profile" +msgstr "" + +#: templates/_header_bar.html:89 +msgid "Admin page" +msgstr "" + +#: templates/_header_bar.html:92 +msgid "User page" +msgstr "" + +#: templates/_header_bar.html:97 +msgid "Logout" +msgstr "" + +#: templates/_message.html:6 +msgid "" +"\n" +" Your account has expired, please contact the administrator.\n" +" " +msgstr "" + +#: templates/_message.html:13 +msgid "Your account will at" +msgstr "" + +#: templates/_message.html:13 templates/_message.html:30 +msgid "expired. " +msgstr "" + +#: templates/_message.html:23 +#, python-format +msgid "" +"\n" +" Your password has expired, please click this link update password.\n" +" " +msgstr "" + +#: templates/_message.html:30 +msgid "Your password will at" +msgstr "" + +#: templates/_message.html:31 +#, python-format +msgid "" +"\n" +" please click this " +"link to update your password.\n" +" " +msgstr "" + +#: templates/_message.html:43 +#, python-format +msgid "" +"\n" +" Your information was incomplete. Please click this link to complete your information.\n" +" " +msgstr "" + +#: templates/_message.html:56 +#, python-format +msgid "" +"\n" +" Your ssh public key not set or expired. Please click this link to update\n" +" " +msgstr "" + +#: templates/_mfa_login_field.html:28 +msgid "Send verification code" +msgstr "" + +#: templates/_mfa_login_field.html:107 +#: users/templates/users/forgot_password.html:176 +msgid "Wait: " +msgstr "" + +#: templates/_mfa_login_field.html:117 +#: users/templates/users/forgot_password.html:192 +msgid "The verification code has been sent" +msgstr "" + +#: templates/_without_nav_base.html:26 +msgid "Home page" +msgstr "" + +#: templates/resource_download.html:18 templates/resource_download.html:33 +#: users/const.py:65 +msgid "Client" +msgstr "" + +#: templates/resource_download.html:20 +msgid "" +"JumpServer Client, currently used to launch the client, now only support " +"launch RDP SSH client, The Telnet client will next" +msgstr "" + +#: templates/resource_download.html:33 +msgid "Microsoft" +msgstr "" + +#: templates/resource_download.html:33 +msgid "Official" +msgstr "" + +#: templates/resource_download.html:35 +msgid "" +"macOS needs to download the client to connect RDP asset, which comes with " +"Windows" +msgstr "" + +#: templates/resource_download.html:44 +msgid "Windows Remote application publisher tools" +msgstr "" + +#: templates/resource_download.html:45 +msgid "" +"OpenSSH is a program used to connect remote applications in the Windows " +"Remote Application Publisher" +msgstr "" + +#: templates/resource_download.html:53 +msgid "Offline video player" +msgstr "" + +#: terminal/api/applet/applet.py:52 terminal/api/applet/applet.py:55 +#: terminal/api/virtualapp/virtualapp.py:43 +#: terminal/api/virtualapp/virtualapp.py:46 +msgid "Invalid zip file" +msgstr "" + +#: terminal/api/applet/applet.py:74 +msgid "This is enterprise edition applet" +msgstr "" + +#: terminal/api/component/endpoint.py:32 +msgid "Not found protocol query params" +msgstr "" + +#: terminal/api/component/storage.py:31 +msgid "Deleting the default storage is not allowed" +msgstr "" + +#: terminal/api/component/storage.py:34 +msgid "Cannot delete storage that is being used" +msgstr "" + +#: terminal/api/component/storage.py:75 terminal/api/component/storage.py:76 +msgid "Command storages" +msgstr "" + +#: terminal/api/component/storage.py:82 +msgid "Invalid" +msgstr "" + +#: terminal/api/component/storage.py:130 terminal/tasks.py:149 +msgid "Test failure: {}" +msgstr "" + +#: terminal/api/component/storage.py:133 +msgid "Test successful" +msgstr "" + +#: terminal/api/component/storage.py:135 +msgid "Test failure: Please check configuration" +msgstr "" + +#: terminal/api/component/terminal.py:55 +msgid "Have online sessions" +msgstr "" + +#: terminal/api/session/session.py:48 +#, python-format +msgid "User %s %s session %s replay" +msgstr "" + +#: terminal/api/session/session.py:317 +msgid "Session does not exist: {}" +msgstr "" + +#: terminal/api/session/session.py:320 +msgid "Session is finished or the protocol not supported" +msgstr "" + +#: terminal/api/session/session.py:333 +msgid "User does not have permission" +msgstr "" + +#: terminal/api/session/sharing.py:29 +msgid "Secure session sharing settings is disabled" +msgstr "" + +#: terminal/apps.py:9 +msgid "App Terminals" +msgstr "" + +#: terminal/backends/command/models.py:19 +msgid "Input" +msgstr "" + +#: terminal/backends/command/models.py:20 terminal/serializers/command.py:73 +msgid "Output" +msgstr "" + +#: terminal/backends/command/models.py:24 terminal/serializers/command.py:22 +#: terminal/templates/terminal/_msg_command_warning.html:10 +msgid "Risk level" +msgstr "" + +#: terminal/connect_methods.py:29 +msgid "SSH Client" +msgstr "" + +#: terminal/connect_methods.py:30 +msgid "SSH Guide" +msgstr "" + +#: terminal/connect_methods.py:31 +msgid "SFTP Client" +msgstr "" + +#: terminal/connect_methods.py:33 +msgid "DB Guide" +msgstr "" + +#: terminal/connect_methods.py:34 +msgid "DB Client" +msgstr "" + +#: terminal/connect_methods.py:36 +msgid "Remote Desktop" +msgstr "" + +#: terminal/connect_methods.py:37 +msgid "RDP Guide" +msgstr "" + +#: terminal/const.py:10 +msgid "Warning" +msgstr "" + +#: terminal/const.py:12 +msgid "Review & Reject" +msgstr "" + +#: terminal/const.py:13 +msgid "Review & Accept" +msgstr "" + +#: terminal/const.py:14 +msgid "Review & Cancel" +msgstr "" + +#: terminal/const.py:45 +msgid "Critical" +msgstr "" + +#: terminal/const.py:46 +msgid "High" +msgstr "" + +#: terminal/const.py:47 terminal/const.py:84 +#: users/templates/users/reset_password.html:50 +msgid "Normal" +msgstr "" + +#: terminal/const.py:48 +msgid "Offline" +msgstr "" + +#: terminal/const.py:80 +msgid "Mismatch" +msgstr "" + +#: terminal/const.py:85 +msgid "Tunnel" +msgstr "" + +#: terminal/const.py:91 +msgid "Read only" +msgstr "" + +#: terminal/const.py:92 +msgid "Writable" +msgstr "" + +#: terminal/const.py:96 +msgid "Kill session" +msgstr "" + +#: terminal/const.py:97 +msgid "Lock session" +msgstr "" + +#: terminal/const.py:98 +msgid "Unlock session" +msgstr "" + +#: terminal/const.py:103 +msgid "Replay create failed" +msgstr "" + +#: terminal/const.py:104 +msgid "Replay upload failed" +msgstr "" + +#: terminal/const.py:105 +msgid "Replay convert failed" +msgstr "" + +#: terminal/const.py:106 +msgid "Replay unsupported" +msgstr "" + +#: terminal/exceptions.py:8 +msgid "Bulk create not support" +msgstr "" + +#: terminal/exceptions.py:13 +msgid "Storage is invalid" +msgstr "" + +#: terminal/models/applet/applet.py:30 xpack/plugins/license/models.py:88 +msgid "Community edition" +msgstr "" + +#: terminal/models/applet/applet.py:31 +msgid "Enterprise" +msgstr "" + +#: terminal/models/applet/applet.py:36 +#: terminal/models/virtualapp/virtualapp.py:22 +msgid "Author" +msgstr "" + +#: terminal/models/applet/applet.py:38 terminal/serializers/applet.py:31 +msgid "Edition" +msgstr "" + +#: terminal/models/applet/applet.py:43 +msgid "Can concurrent" +msgstr "" + +#: terminal/models/applet/applet.py:44 +#: terminal/models/virtualapp/virtualapp.py:29 +msgid "Tags" +msgstr "" + +#: terminal/models/applet/applet.py:48 terminal/serializers/applet_host.py:167 +#: terminal/serializers/storage.py:197 +msgid "Hosts" +msgstr "" + +#: terminal/models/applet/applet.py:93 +#: terminal/models/virtualapp/virtualapp.py:66 +msgid "Applet pkg not valid, Missing file {}" +msgstr "" + +#: terminal/models/applet/applet.py:112 +msgid "Load platform.yml failed: {}" +msgstr "" + +#: terminal/models/applet/applet.py:115 +msgid "Only support custom platform" +msgstr "" + +#: terminal/models/applet/applet.py:120 +msgid "Missing type in platform.yml" +msgstr "" + +#: terminal/models/applet/applet.py:319 terminal/models/applet/host.py:36 +#: terminal/models/applet/host.py:138 +msgid "Hosting" +msgstr "" + +#: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:69 +msgid "Deploy options" +msgstr "" + +#: terminal/models/applet/host.py:19 +msgid "Auto create accounts" +msgstr "" + +#: terminal/models/applet/host.py:20 +msgid "Accounts create amount" +msgstr "" + +#: terminal/models/applet/host.py:21 +msgid "Inited" +msgstr "" + +#: terminal/models/applet/host.py:22 +msgid "Date inited" +msgstr "" + +#: terminal/models/applet/host.py:23 +msgid "Date synced" +msgstr "" + +#: terminal/models/applet/host.py:28 +msgid "Using same account" +msgstr "" + +#: terminal/models/applet/host.py:139 +msgid "Initial" +msgstr "" + +#: terminal/models/component/endpoint.py:15 +msgid "HTTPS port" +msgstr "" + +#: terminal/models/component/endpoint.py:16 +msgid "HTTP port" +msgstr "" + +#: terminal/models/component/endpoint.py:17 +msgid "SSH port" +msgstr "" + +#: terminal/models/component/endpoint.py:18 +msgid "RDP port" +msgstr "" + +#: terminal/models/component/endpoint.py:19 +msgid "MySQL port" +msgstr "" + +#: terminal/models/component/endpoint.py:20 +msgid "MariaDB port" +msgstr "" + +#: terminal/models/component/endpoint.py:21 +msgid "PostgreSQL port" +msgstr "" + +#: terminal/models/component/endpoint.py:22 +msgid "Redis port" +msgstr "" + +#: terminal/models/component/endpoint.py:23 +msgid "SQLServer port" +msgstr "" + +#: terminal/models/component/endpoint.py:30 +#: terminal/models/component/endpoint.py:117 +#: terminal/serializers/endpoint.py:73 terminal/serializers/storage.py:41 +#: terminal/serializers/storage.py:53 terminal/serializers/storage.py:83 +#: terminal/serializers/storage.py:93 terminal/serializers/storage.py:101 +msgid "Endpoint" +msgstr "" + +#: terminal/models/component/endpoint.py:123 +msgid "Endpoint rule" +msgstr "" + +#: terminal/models/component/status.py:15 +msgid "Session Online" +msgstr "" + +#: terminal/models/component/status.py:16 +msgid "CPU Load" +msgstr "" + +#: terminal/models/component/status.py:17 +msgid "Memory Used" +msgstr "" + +#: terminal/models/component/status.py:18 +msgid "Disk Used" +msgstr "" + +#: terminal/models/component/status.py:19 +msgid "Connections" +msgstr "" + +#: terminal/models/component/status.py:20 +msgid "Threads" +msgstr "" + +#: terminal/models/component/status.py:21 +msgid "Boot Time" +msgstr "" + +#: terminal/models/component/storage.py:28 +msgid "Default storage" +msgstr "" + +#: terminal/models/component/storage.py:140 +#: terminal/models/component/terminal.py:91 +msgid "Command storage" +msgstr "" + +#: terminal/models/component/storage.py:204 +#: terminal/models/component/terminal.py:92 +msgid "Replay storage" +msgstr "" + +#: terminal/models/component/terminal.py:88 +msgid "type" +msgstr "" + +#: terminal/models/component/terminal.py:90 terminal/serializers/command.py:76 +msgid "Remote Address" +msgstr "" + +#: terminal/models/component/terminal.py:93 +msgid "Application User" +msgstr "" + +#: terminal/models/component/terminal.py:177 +msgid "Can view terminal config" +msgstr "" + +#: terminal/models/session/command.py:76 +msgid "Command record" +msgstr "" + +#: terminal/models/session/replay.py:12 +msgid "Session replay" +msgstr "" + +#: terminal/models/session/replay.py:14 +msgid "Can upload session replay" +msgstr "" + +#: terminal/models/session/replay.py:15 +msgid "Can download session replay" +msgstr "" + +#: terminal/models/session/session.py:35 +msgid "Account ID" +msgstr "" + +#: terminal/models/session/session.py:37 terminal/models/session/sharing.py:118 +msgid "Login from" +msgstr "" + +#: terminal/models/session/session.py:42 +msgid "Replay" +msgstr "" + +#: terminal/models/session/session.py:48 terminal/serializers/session.py:68 +msgid "Command amount" +msgstr "" + +#: terminal/models/session/session.py:49 terminal/serializers/session.py:30 +msgid "Error reason" +msgstr "" + +#: terminal/models/session/session.py:290 +msgid "Session record" +msgstr "" + +#: terminal/models/session/session.py:292 +msgid "Can monitor session" +msgstr "" + +#: terminal/models/session/session.py:293 +msgid "Can share session" +msgstr "" + +#: terminal/models/session/session.py:294 +msgid "Can terminate session" +msgstr "" + +#: terminal/models/session/session.py:295 +msgid "Can validate session action perm" +msgstr "" + +#: terminal/models/session/sharing.py:32 +msgid "Expired time (min)" +msgstr "" + +#: terminal/models/session/sharing.py:36 terminal/serializers/sharing.py:20 +#: terminal/serializers/sharing.py:52 +msgid "Action permission" +msgstr "" + +#: terminal/models/session/sharing.py:38 +msgid "Origin" +msgstr "" + +#: terminal/models/session/sharing.py:42 terminal/models/session/sharing.py:100 +#: terminal/notifications.py:261 +msgid "Session sharing" +msgstr "" + +#: terminal/models/session/sharing.py:44 +msgid "Can add super session sharing" +msgstr "" + +#: terminal/models/session/sharing.py:83 +msgid "Link not active" +msgstr "" + +#: terminal/models/session/sharing.py:85 +msgid "Link expired" +msgstr "" + +#: terminal/models/session/sharing.py:87 +msgid "User not allowed to join" +msgstr "" + +#: terminal/models/session/sharing.py:104 terminal/serializers/sharing.py:71 +msgid "Joiner" +msgstr "" + +#: terminal/models/session/sharing.py:107 +msgid "Date joined" +msgstr "" + +#: terminal/models/session/sharing.py:110 +msgid "Date left" +msgstr "" + +#: terminal/models/session/sharing.py:133 +msgid "Session join record" +msgstr "" + +#: terminal/models/session/sharing.py:149 +msgid "Invalid verification code" +msgstr "" + +#: terminal/models/session/sharing.py:156 +msgid "You have already joined this session" +msgstr "" + +#: terminal/models/virtualapp/provider.py:11 +msgid "Hostname" +msgstr "" + +#: terminal/models/virtualapp/virtualapp.py:32 +msgid "Providers" +msgstr "" + +#: terminal/models/virtualapp/virtualapp.py:94 +#: terminal/serializers/virtualapp.py:34 +msgid "App Provider" +msgstr "" + +#: terminal/models/virtualapp/virtualapp.py:102 +msgid "Virtual app publication" +msgstr "" + +#: terminal/notifications.py:25 +msgid "Sessions" +msgstr "" + +#: terminal/notifications.py:72 +msgid "Command warning" +msgstr "" + +#: terminal/notifications.py:130 terminal/notifications.py:175 +msgid "Command reject" +msgstr "" + +#: terminal/notifications.py:157 terminal/notifications.py:206 +msgid "Level" +msgstr "" + +#: terminal/notifications.py:224 +msgid "Command and replay storage" +msgstr "" + +#: terminal/notifications.py:240 terminal/tasks.py:153 +msgid "Test failure: Account invalid" +msgstr "" + +#: terminal/notifications.py:250 +#: terminal/templates/terminal/_msg_check_command_replay_storage_connectivity.html:4 +msgid "Invalid storage" +msgstr "" + +#: terminal/serializers/applet.py:28 terminal/serializers/virtualapp.py:15 +msgid "Icon" +msgstr "" + +#: terminal/serializers/applet_host.py:24 +msgid "Per Session" +msgstr "" + +#: terminal/serializers/applet_host.py:25 +msgid "Per Device" +msgstr "" + +#: terminal/serializers/applet_host.py:37 +msgid "Core API" +msgstr "" + +#: terminal/serializers/applet_host.py:38 +msgid "" +" \n" +" Tips: The application release machine communicates with the Core " +"service. \n" +" If the release machine and the Core service are on the same network " +"segment, \n" +" it is recommended to fill in the intranet address, otherwise fill in " +"the current site URL \n" +"
\n" +" eg: https://172.16.10.110 or https://dev.jumpserver.com\n" +" " +msgstr "" + +#: terminal/serializers/applet_host.py:46 terminal/serializers/storage.py:208 +msgid "Ignore Certificate Verification" +msgstr "" + +#: terminal/serializers/applet_host.py:47 +msgid "Existing RDS license" +msgstr "" + +#: terminal/serializers/applet_host.py:48 +msgid "RDS License Server" +msgstr "" + +#: terminal/serializers/applet_host.py:49 +msgid "RDS Licensing Mode" +msgstr "" + +#: terminal/serializers/applet_host.py:51 +msgid "RDS Single Session Per User" +msgstr "" + +#: terminal/serializers/applet_host.py:53 +msgid "RDS Max Disconnection Time (ms)" +msgstr "" + +#: terminal/serializers/applet_host.py:55 +msgid "" +"Tips: Set the maximum duration for keeping a disconnected session active on " +"the server (log off the session after 60000 milliseconds)." +msgstr "" + +#: terminal/serializers/applet_host.py:60 +msgid "RDS Remote App Logoff Time Limit (ms)" +msgstr "" + +#: terminal/serializers/applet_host.py:62 +msgid "" +"Tips: Set the logoff time for RemoteApp sessions after closing all RemoteApp " +"programs (0 milliseconds, log off the session immediately)." +msgstr "" + +#: terminal/serializers/applet_host.py:71 terminal/serializers/terminal.py:47 +#: terminal/serializers/virtualapp_provider.py:13 +msgid "Load status" +msgstr "" + +#: terminal/serializers/applet_host.py:85 +msgid "" +"These accounts are used to connect to the published application, the account " +"is now divided into two types, one is dedicated to each account, each user " +"has a private account, the other is public, when the application does not " +"support multiple open and the special has been used, the public account will " +"be used to connect" +msgstr "" + +#: terminal/serializers/applet_host.py:92 +msgid "The number of public accounts created automatically" +msgstr "" + +#: terminal/serializers/applet_host.py:95 +msgid "" +"Connect to the host using the same account first. For security reasons, " +"please set the configuration item CACHE_LOGIN_PASSWORD_ENABLED=true and " +"restart the service to enable it." +msgstr "" + +#: terminal/serializers/applet_host.py:137 +msgid "Install applets" +msgstr "" + +#: terminal/serializers/applet_host.py:167 +msgid "Host ID" +msgstr "" + +#: terminal/serializers/applet_host.py:168 +msgid "Applet ID" +msgstr "" + +#: terminal/serializers/command.py:19 +msgid "Session ID" +msgstr "" + +#: terminal/serializers/command.py:41 +msgid "Command Filter ACL" +msgstr "" + +#: terminal/serializers/command.py:44 +msgid "Command Group" +msgstr "" + +#: terminal/serializers/command.py:55 +msgid "Invalid command filter ACL id" +msgstr "" + +#: terminal/serializers/command.py:59 +msgid "Invalid command group id" +msgstr "" + +#: terminal/serializers/command.py:63 +msgid "Invalid session id" +msgstr "" + +#: terminal/serializers/command.py:74 +msgid "Timestamp" +msgstr "" + +#: terminal/serializers/endpoint.py:15 +msgid "Oracle port" +msgstr "" + +#: terminal/serializers/endpoint.py:18 +msgid "Oracle port range" +msgstr "" + +#: terminal/serializers/endpoint.py:20 +msgid "" +"Oracle proxy server listen port is dynamic, Each additional Oracle database " +"instance adds a port listener" +msgstr "" + +#: terminal/serializers/endpoint.py:38 +msgid "" +"The host address accessed when connecting to assets, if it is empty, the " +"access address of the current browser will be used (the default endpoint " +"does not allow modification of the host)" +msgstr "" + +#: terminal/serializers/endpoint.py:64 +msgid "" +"The assets within this IP range, the following endpoint will be used for the " +"connection" +msgstr "" + +#: terminal/serializers/endpoint.py:65 +msgid "" +"If asset IP addresses under different endpoints conflict, use asset labels" +msgstr "" + +#: terminal/serializers/endpoint.py:69 +msgid "Asset IP" +msgstr "" + +#: terminal/serializers/session.py:25 terminal/serializers/session.py:53 +msgid "Can replay" +msgstr "" + +#: terminal/serializers/session.py:26 terminal/serializers/session.py:54 +msgid "Can join" +msgstr "" + +#: terminal/serializers/session.py:27 terminal/serializers/session.py:57 +msgid "Can terminate" +msgstr "" + +#: terminal/serializers/session.py:47 +msgid "Duration" +msgstr "" + +#: terminal/serializers/session.py:49 +msgid "User ID" +msgstr "" + +#: terminal/serializers/session.py:50 +msgid "Asset ID" +msgstr "" + +#: terminal/serializers/session.py:51 +msgid "Login from display" +msgstr "" + +#: terminal/serializers/session.py:58 +msgid "Terminal display" +msgstr "" + +#: terminal/serializers/storage.py:23 +msgid "Endpoint invalid: remove path `{}`" +msgstr "" + +#: terminal/serializers/storage.py:29 +msgid "Bucket" +msgstr "" + +#: terminal/serializers/storage.py:33 +msgid "Access key ID" +msgstr "" + +#: terminal/serializers/storage.py:37 +#: xpack/plugins/cloud/serializers/account_attrs.py:20 +msgid "Access key secret" +msgstr "" + +#: terminal/serializers/storage.py:68 xpack/plugins/cloud/models.py:253 +msgid "Region" +msgstr "" + +#: terminal/serializers/storage.py:112 +msgid "Container name" +msgstr "" + +#: terminal/serializers/storage.py:115 +msgid "Account key" +msgstr "" + +#: terminal/serializers/storage.py:118 +msgid "Endpoint suffix" +msgstr "" + +#: terminal/serializers/storage.py:129 +msgid "HOST" +msgstr "" + +#: terminal/serializers/storage.py:146 users/models/user.py:904 +#: xpack/plugins/cloud/serializers/account_attrs.py:213 +msgid "Private key" +msgstr "" + +#: terminal/serializers/storage.py:152 +msgid "SFTP Root" +msgstr "" + +#: terminal/serializers/storage.py:173 +msgid "The address cannot contain the special character `#`" +msgstr "" + +#: terminal/serializers/storage.py:175 +msgid "The address format is incorrect" +msgstr "" + +#: terminal/serializers/storage.py:182 +msgid "Host invalid" +msgstr "" + +#: terminal/serializers/storage.py:185 +msgid "Port invalid" +msgstr "" + +#: terminal/serializers/storage.py:200 +msgid "Index by date" +msgstr "" + +#: terminal/serializers/storage.py:201 +msgid "Whether to create an index by date" +msgstr "" + +#: terminal/serializers/storage.py:204 +msgid "Index" +msgstr "" + +#: terminal/serializers/storage.py:206 +msgid "Doc type" +msgstr "" + +#: terminal/serializers/task.py:9 +msgid "Session id" +msgstr "" + +#: terminal/serializers/terminal.py:42 +msgid "Online sessions" +msgstr "" + +#: terminal/serializers/terminal.py:43 +msgid "Is alive" +msgstr "" + +#: terminal/serializers/terminal.py:49 +msgid "Stat" +msgstr "" + +#: terminal/serializers/terminal.py:83 terminal/serializers/terminal.py:91 +msgid "Not found" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:26 +msgid "Container ID" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:27 +msgid "Container Image" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:28 +msgid "Container Name" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:29 +msgid "Container Status" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:30 +msgid "Container Ports" +msgstr "" + +#: terminal/session_lifecycle.py:30 +#, python-format +msgid "Connect to asset %s success" +msgstr "" + +#: terminal/session_lifecycle.py:38 +#, python-format +msgid "Connect to asset %s finished: %s" +msgstr "" + +#: terminal/session_lifecycle.py:48 +#, python-format +msgid "User %s create share link" +msgstr "" + +#: terminal/session_lifecycle.py:57 +#, python-format +msgid "User %s join session" +msgstr "" + +#: terminal/session_lifecycle.py:69 +#, python-format +msgid "User %s leave session" +msgstr "" + +#: terminal/session_lifecycle.py:81 +#, python-format +msgid "User %s join to monitor session" +msgstr "" + +#: terminal/session_lifecycle.py:93 +#, python-format +msgid "User %s exit to monitor session" +msgstr "" + +#: terminal/session_lifecycle.py:105 +msgid "Replay start to convert" +msgstr "" + +#: terminal/session_lifecycle.py:113 +msgid "Replay successfully converted to MP4 format" +msgstr "" + +#: terminal/session_lifecycle.py:121 +#, python-format +msgid "Replay failed to convert to MP4 format: %s" +msgstr "" + +#: terminal/session_lifecycle.py:129 +msgid "Replay start to upload" +msgstr "" + +#: terminal/session_lifecycle.py:137 +msgid "Replay successfully uploaded" +msgstr "" + +#: terminal/session_lifecycle.py:145 +#, python-format +msgid "Replay failed to upload: %s" +msgstr "" + +#: terminal/session_lifecycle.py:152 +msgid "connect failed" +msgstr "" + +#: terminal/session_lifecycle.py:153 +msgid "connection disconnect" +msgstr "" + +#: terminal/session_lifecycle.py:154 +msgid "user closed" +msgstr "" + +#: terminal/session_lifecycle.py:155 +msgid "idle disconnect" +msgstr "" + +#: terminal/session_lifecycle.py:156 +msgid "admin terminated" +msgstr "" + +#: terminal/session_lifecycle.py:157 +msgid "maximum session time has been reached" +msgstr "" + +#: terminal/session_lifecycle.py:158 +msgid "permission has expired" +msgstr "" + +#: terminal/session_lifecycle.py:159 +msgid "storage is null" +msgstr "" + +#: terminal/tasks.py:31 +msgid "Periodic delete terminal status" +msgstr "" + +#: terminal/tasks.py:39 +msgid "Clean orphan session" +msgstr "" + +#: terminal/tasks.py:87 +msgid "Run applet host deployment" +msgstr "" + +#: terminal/tasks.py:97 +msgid "Install applet" +msgstr "" + +#: terminal/tasks.py:108 +msgid "Uninstall applet" +msgstr "" + +#: terminal/tasks.py:119 +msgid "Generate applet host accounts" +msgstr "" + +#: terminal/tasks.py:131 +msgid "Check command replay storage connectivity" +msgstr "" + +#: terminal/templates/terminal/_msg_command_alert.html:10 +msgid "view" +msgstr "" + +#: terminal/utils/db_port_mapper.py:85 +msgid "" +"No available port is matched. The number of databases may have exceeded the " +"number of ports open to the database agent service, Contact the " +"administrator to open more ports." +msgstr "" + +#: terminal/utils/db_port_mapper.py:113 +msgid "" +"No ports can be used, check and modify the limit on the number of ports that " +"Magnus listens on in the configuration file." +msgstr "" + +#: terminal/utils/db_port_mapper.py:115 +msgid "All available port count: {}, Already use port count: {}" +msgstr "" + +#: tickets/api/ticket.py:88 tickets/models/ticket/general.py:286 +msgid "Applicant" +msgstr "" + +#: tickets/apps.py:7 +msgid "App Tickets" +msgstr "" + +#: tickets/const.py:10 +msgid "Apply for asset" +msgstr "" + +#: tickets/const.py:17 tickets/const.py:24 tickets/const.py:42 +msgid "Open" +msgstr "" + +#: tickets/const.py:19 tickets/const.py:31 +msgid "Approved" +msgstr "" + +#: tickets/const.py:20 tickets/const.py:32 +msgid "Rejected" +msgstr "" + +#: tickets/const.py:30 tickets/const.py:37 +msgid "Closed" +msgstr "" + +#: tickets/const.py:49 +msgid "One level" +msgstr "" + +#: tickets/const.py:50 +msgid "Two level" +msgstr "" + +#: tickets/const.py:54 +msgid "Org admin" +msgstr "" + +#: tickets/const.py:55 +msgid "Custom user" +msgstr "" + +#: tickets/const.py:56 +msgid "Super admin" +msgstr "" + +#: tickets/const.py:57 +msgid "Super admin and org admin" +msgstr "" + +#: tickets/const.py:61 +msgid "All assets" +msgstr "" + +#: tickets/const.py:62 +msgid "Permed assets" +msgstr "" + +#: tickets/const.py:63 +msgid "Permed valid assets" +msgstr "" + +#: tickets/errors.py:9 +msgid "Ticket already closed" +msgstr "" + +#: tickets/handlers/apply_asset.py:36 +msgid "" +"Created by the ticket ticket title: {} ticket applicant: {} ticket " +"processor: {} ticket ID: {}" +msgstr "" + +#: tickets/handlers/base.py:85 +msgid "Change field" +msgstr "" + +#: tickets/handlers/base.py:85 +msgid "Before change" +msgstr "" + +#: tickets/handlers/base.py:85 +msgid "After change" +msgstr "" + +#: tickets/handlers/base.py:97 +msgid "{} {} the ticket" +msgstr "" + +#: tickets/models/comment.py:14 +msgid "common" +msgstr "" + +#: tickets/models/comment.py:23 +msgid "User display name" +msgstr "" + +#: tickets/models/comment.py:24 +msgid "Body" +msgstr "" + +#: tickets/models/flow.py:19 tickets/models/flow.py:61 +#: tickets/models/ticket/general.py:42 +msgid "Approve level" +msgstr "" + +#: tickets/models/flow.py:24 tickets/serializers/flow.py:17 +msgid "Approve strategy" +msgstr "" + +#: tickets/models/flow.py:29 tickets/serializers/flow.py:19 +msgid "Assignees" +msgstr "" + +#: tickets/models/flow.py:33 +msgid "Ticket flow approval rule" +msgstr "" + +#: tickets/models/flow.py:66 +msgid "Ticket flow" +msgstr "" + +#: tickets/models/relation.py:12 +msgid "Ticket session relation" +msgstr "" + +#: tickets/models/ticket/apply_application.py:10 +#: tickets/models/ticket/apply_asset.py:13 +msgid "Permission name" +msgstr "" + +#: tickets/models/ticket/apply_application.py:19 +msgid "Apply applications" +msgstr "" + +#: tickets/models/ticket/apply_application.py:22 +msgid "Apply system users" +msgstr "" + +#: tickets/models/ticket/apply_asset.py:9 +#: tickets/serializers/ticket/apply_asset.py:14 +msgid "Select at least one asset or node" +msgstr "" + +#: tickets/models/ticket/apply_asset.py:17 +msgid "Apply accounts" +msgstr "" + +#: tickets/models/ticket/apply_asset.py:26 +msgid "Apply Asset Ticket" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:9 +msgid "Run user" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:11 +msgid "Run asset" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:12 +msgid "Run command" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:19 +msgid "Command filter acl" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:23 +msgid "Apply Command Ticket" +msgstr "" + +#: tickets/models/ticket/general.py:77 +msgid "Ticket step" +msgstr "" + +#: tickets/models/ticket/general.py:95 +msgid "Ticket assignee" +msgstr "" + +#: tickets/models/ticket/general.py:270 +msgid "Title" +msgstr "" + +#: tickets/models/ticket/general.py:290 +msgid "TicketFlow" +msgstr "" + +#: tickets/models/ticket/general.py:293 +msgid "Approval step" +msgstr "" + +#: tickets/models/ticket/general.py:296 +msgid "Relation snapshot" +msgstr "" + +#: tickets/models/ticket/general.py:399 +msgid "Please try again" +msgstr "" + +#: tickets/models/ticket/general.py:475 +msgid "Super ticket" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:11 +msgid "Login user" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:14 +msgid "Login asset" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:17 +msgid "Login account" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:27 +msgid "Apply Login Asset Ticket" +msgstr "" + +#: tickets/models/ticket/login_confirm.py:15 +msgid "Apply Login Ticket" +msgstr "" + +#: tickets/notifications.py:63 +msgid "Ticket basic info" +msgstr "" + +#: tickets/notifications.py:64 +msgid "Ticket applied info" +msgstr "" + +#: tickets/notifications.py:105 +msgid "Your has a new ticket, applicant - {}" +msgstr "" + +#: tickets/notifications.py:109 +msgid "{}: New Ticket - {} ({})" +msgstr "" + +#: tickets/notifications.py:155 +msgid "Your ticket has been processed, processor - {}" +msgstr "" + +#: tickets/notifications.py:159 +msgid "Ticket has processed - {} ({})" +msgstr "" + +#: tickets/serializers/flow.py:20 +msgid "Assignees display" +msgstr "" + +#: tickets/serializers/flow.py:46 +msgid "Please select the Assignees" +msgstr "" + +#: tickets/serializers/flow.py:74 +msgid "The current organization type already exists" +msgstr "" + +#: tickets/serializers/super_ticket.py:15 +msgid "Processor" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:16 +msgid "Support fuzzy search, and display up to 10 items" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:22 +msgid "Apply assets" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:26 +msgid "Apply nodes" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:28 +msgid "Apply actions" +msgstr "" + +#: tickets/serializers/ticket/common.py:15 +#: tickets/serializers/ticket/common.py:75 +msgid "Created by ticket ({}-{})" +msgstr "" + +#: tickets/serializers/ticket/common.py:67 +msgid "The expiration date should be greater than the start date" +msgstr "" + +#: tickets/serializers/ticket/common.py:82 +msgid "Permission named `{}` already exists" +msgstr "" + +#: tickets/serializers/ticket/ticket.py:89 +msgid "The ticket flow `{}` does not exist" +msgstr "" + +#: tickets/templates/tickets/_msg_ticket.html:21 +msgid "View details" +msgstr "" + +#: tickets/templates/tickets/_msg_ticket.html:26 +msgid "Direct approval" +msgstr "" + +#: tickets/templates/tickets/approve_check_password.html:11 +msgid "Ticket information" +msgstr "" + +#: tickets/templates/tickets/approve_check_password.html:28 +#: tickets/views/approve.py:43 tickets/views/approve.py:80 +msgid "Ticket approval" +msgstr "" + +#: tickets/templates/tickets/approve_check_password.html:43 +msgid "Approval" +msgstr "" + +#: tickets/views/approve.py:44 +msgid "" +"This ticket does not exist, the process has ended, or this link has expired" +msgstr "" + +#: tickets/views/approve.py:72 +msgid "Click the button below to approve or reject" +msgstr "" + +#: tickets/views/approve.py:81 +msgid "After successful authentication, this ticket can be approved directly" +msgstr "" + +#: tickets/views/approve.py:105 +msgid "Illegal approval action" +msgstr "" + +#: tickets/views/approve.py:119 +msgid "This user is not authorized to approve this ticket" +msgstr "" + +#: users/api/user.py:155 +msgid "Can not invite self" +msgstr "" + +#: users/api/user.py:208 +msgid "Could not reset self otp, use profile reset instead" +msgstr "" + +#: users/apps.py:9 +msgid "App Users" +msgstr "" + +#: users/const.py:10 +msgid "System administrator" +msgstr "" + +#: users/const.py:11 +msgid "System auditor" +msgstr "" + +#: users/const.py:12 +msgid "Organization administrator" +msgstr "" + +#: users/const.py:13 +msgid "Organization auditor" +msgstr "" + +#: users/const.py:18 +msgid "Reset link will be generated and sent to the user" +msgstr "" + +#: users/const.py:19 +msgid "Set password" +msgstr "" + +#: users/const.py:23 +msgid "AUTO" +msgstr "" + +#: users/const.py:31 +msgid "Full screen" +msgstr "" + +#: users/const.py:32 +msgid "Multi screen" +msgstr "" + +#: users/const.py:33 +msgid "Drives redirect" +msgstr "" + +#: users/const.py:37 +msgid "Current window" +msgstr "" + +#: users/const.py:38 +msgid "New window" +msgstr "" + +#: users/const.py:47 +msgid "High(32 bit)" +msgstr "" + +#: users/const.py:48 +msgid "Medium(16 bit)" +msgstr "" + +#: users/const.py:69 +msgid "Replace" +msgstr "" + +#: users/const.py:70 +msgid "Suffix" +msgstr "" + +#: users/exceptions.py:10 +msgid "MFA not enabled" +msgstr "" + +#: users/exceptions.py:20 +msgid "Unable to delete all users" +msgstr "" + +#: users/forms/profile.py:48 +msgid "" +"When enabled, you will enter the MFA binding process the next time you log " +"in. you can also directly bind in \"personal information -> quick " +"modification -> change MFA Settings\"!" +msgstr "" + +#: users/forms/profile.py:59 +msgid "* Enable MFA to make the account more secure." +msgstr "" + +#: users/forms/profile.py:68 +msgid "" +"In order to protect you and your company, please keep your account, password " +"and key sensitive information properly. (for example: setting complex " +"password, enabling MFA)" +msgstr "" + +#: users/forms/profile.py:75 +msgid "Finish" +msgstr "" + +#: users/forms/profile.py:82 +msgid "New password" +msgstr "" + +#: users/forms/profile.py:87 +msgid "Confirm password" +msgstr "" + +#: users/forms/profile.py:95 +msgid "Password does not match" +msgstr "" + +#: users/forms/profile.py:104 +msgid "The phone number must contain an area code, for example, +86" +msgstr "" + +#: users/forms/profile.py:120 +msgid "Old password" +msgstr "" + +#: users/forms/profile.py:130 +msgid "Old password error" +msgstr "" + +#: users/forms/profile.py:140 +msgid "Automatically configure and download the SSH key" +msgstr "" + +#: users/forms/profile.py:142 +msgid "ssh public key" +msgstr "" + +#: users/forms/profile.py:143 +msgid "ssh-rsa AAAA..." +msgstr "" + +#: users/forms/profile.py:144 +msgid "Paste your id_rsa.pub here." +msgstr "" + +#: users/forms/profile.py:157 +msgid "Public key should not be the same as your old one." +msgstr "" + +#: users/forms/profile.py:161 users/serializers/profile.py:76 +#: users/serializers/profile.py:165 users/serializers/profile.py:192 +msgid "Not a valid ssh public key" +msgstr "" + +#: users/forms/profile.py:172 users/models/user.py:907 +#: xpack/plugins/cloud/serializers/account_attrs.py:210 +msgid "Public key" +msgstr "" + +#: users/models/preference.py:38 users/serializers/preference/preference.py:19 +msgid "Preference" +msgstr "" + +#: users/models/user.py:656 users/serializers/profile.py:94 +msgid "Force enable" +msgstr "" + +#: users/models/user.py:761 +msgid "Lark" +msgstr "" + +#: users/models/user.py:886 users/serializers/user.py:182 +msgid "Is service account" +msgstr "" + +#: users/models/user.py:888 +msgid "Avatar" +msgstr "" + +#: users/models/user.py:891 +msgid "Wechat" +msgstr "" + +#: users/models/user.py:894 users/serializers/user.py:112 +msgid "Phone" +msgstr "" + +#: users/models/user.py:900 +msgid "OTP secret key" +msgstr "" + +#: users/models/user.py:912 users/serializers/profile.py:129 +#: users/serializers/user.py:179 +msgid "Is first login" +msgstr "" + +#: users/models/user.py:921 +msgid "Date password last updated" +msgstr "" + +#: users/models/user.py:924 +msgid "Need update password" +msgstr "" + +#: users/models/user.py:935 +msgid "Date api key used" +msgstr "" + +#: users/models/user.py:1057 +msgid "Can not delete admin user" +msgstr "" + +#: users/models/user.py:1071 +msgid "Can invite user" +msgstr "" + +#: users/models/user.py:1072 +msgid "Can remove user" +msgstr "" + +#: users/models/user.py:1073 +msgid "Can match user" +msgstr "" + +#: users/models/user.py:1082 +msgid "Administrator" +msgstr "" + +#: users/models/user.py:1085 +msgid "Administrator is the super user of system" +msgstr "" + +#: users/models/user.py:1110 +msgid "User password history" +msgstr "" + +#: users/notifications.py:55 +#: users/templates/users/_msg_password_expire_reminder.html:17 +#: users/templates/users/reset_password.html:5 +#: users/templates/users/reset_password.html:6 +msgid "Reset password" +msgstr "" + +#: users/notifications.py:85 users/views/profile/reset.py:233 +msgid "Reset password success" +msgstr "" + +#: users/notifications.py:117 +msgid "Reset public key success" +msgstr "" + +#: users/notifications.py:143 +msgid "Password is about expire" +msgstr "" + +#: users/notifications.py:171 +msgid "Account is about expire" +msgstr "" + +#: users/notifications.py:193 +msgid "Reset SSH Key" +msgstr "" + +#: users/notifications.py:214 +msgid "Reset MFA" +msgstr "" + +#: users/serializers/preference/koko.py:10 +msgid "File name conflict resolution" +msgstr "" + +#: users/serializers/preference/koko.py:14 +msgid "Terminal theme name" +msgstr "" + +#: users/serializers/preference/lina.py:13 +msgid "New file encryption password" +msgstr "" + +#: users/serializers/preference/lina.py:18 +msgid "Confirm file encryption password" +msgstr "" + +#: users/serializers/preference/lina.py:31 users/serializers/profile.py:48 +msgid "The newly set password is inconsistent" +msgstr "" + +#: users/serializers/preference/luna.py:26 +msgid "Async loading of asset tree" +msgstr "" + +#: users/serializers/preference/luna.py:30 +msgid "Connect default open method" +msgstr "" + +#: users/serializers/preference/luna.py:37 +msgid "RDP resolution" +msgstr "" + +#: users/serializers/preference/luna.py:41 +msgid "Keyboard layout" +msgstr "" + +#: users/serializers/preference/luna.py:45 +msgid "RDP client option" +msgstr "" + +#: users/serializers/preference/luna.py:49 +msgid "RDP color quality" +msgstr "" + +#: users/serializers/preference/luna.py:53 +msgid "RDP smart size" +msgstr "" + +#: users/serializers/preference/luna.py:54 +msgid "" +"Determines whether the client computer should scale the content on the " +"remote computer to fit the window size of the client computer when the " +"window is resized." +msgstr "" + +#: users/serializers/preference/luna.py:59 +msgid "Remote application connection method" +msgstr "" + +#: users/serializers/preference/luna.py:66 +msgid "Character terminal font size" +msgstr "" + +#: users/serializers/preference/luna.py:69 +msgid "Backspace as Ctrl+H" +msgstr "" + +#: users/serializers/preference/luna.py:72 +msgid "Right click quickly paste" +msgstr "" + +#: users/serializers/preference/luna.py:78 +msgid "Graphics" +msgstr "" + +#: users/serializers/preference/luna.py:79 +msgid "Command line" +msgstr "" + +#: users/serializers/profile.py:29 +msgid "The old password is incorrect" +msgstr "" + +#: users/serializers/profile.py:36 users/serializers/profile.py:179 +msgid "Password does not match security rules" +msgstr "" + +#: users/serializers/profile.py:40 +msgid "The new password cannot be the last {} passwords" +msgstr "" + +#: users/serializers/user.py:45 +msgid "System roles" +msgstr "" + +#: users/serializers/user.py:49 +msgid "Org roles" +msgstr "" + +#: users/serializers/user.py:52 +msgid "Organizations and roles" +msgstr "" + +#: users/serializers/user.py:94 +msgid "Password setting" +msgstr "" + +#: users/serializers/user.py:96 +msgid "MFA enabled" +msgstr "" + +#: users/serializers/user.py:98 +msgid "MFA force enabled" +msgstr "" + +#: users/serializers/user.py:100 +msgid "Login blocked" +msgstr "" + +#: users/serializers/user.py:103 users/serializers/user.py:188 +msgid "Is OTP bound" +msgstr "" + +#: users/serializers/user.py:104 +msgid "Super Administrator" +msgstr "" + +#: users/serializers/user.py:105 +msgid "Organization Administrator" +msgstr "" + +#: users/serializers/user.py:107 +msgid "Can public key authentication" +msgstr "" + +#: users/serializers/user.py:176 +msgid "Superuser" +msgstr "" + +#: users/serializers/user.py:183 +msgid "Is org admin" +msgstr "" + +#: users/serializers/user.py:185 +msgid "Avatar url" +msgstr "" + +#: users/serializers/user.py:189 +msgid "MFA level" +msgstr "" + +#: users/serializers/user.py:312 +msgid "" +"For security, only a partial of users is displayed. You can search for more" +msgstr "" + +#: users/serializers/user.py:345 +msgid "name not unique" +msgstr "" + +#: users/signal_handlers.py:35 +msgid "" +"The administrator has enabled \"Only allow existing users to log in\", \n" +" and the current user is not in the user list. Please contact the " +"administrator." +msgstr "" + +#: users/signal_handlers.py:169 +msgid "Clean up expired user sessions" +msgstr "" + +#: users/tasks.py:25 +msgid "Check password expired" +msgstr "" + +#: users/tasks.py:39 +msgid "Periodic check password expired" +msgstr "" + +#: users/tasks.py:53 +msgid "Check user expired" +msgstr "" + +#: users/tasks.py:70 +msgid "Periodic check user expired" +msgstr "" + +#: users/tasks.py:84 +msgid "Check unused users" +msgstr "" + +#: users/tasks.py:123 +msgid "The user has not logged in recently and has been disabled." +msgstr "" + +#: users/templates/users/_msg_account_expire_reminder.html:7 +msgid "Your account will expire in" +msgstr "" + +#: users/templates/users/_msg_account_expire_reminder.html:8 +msgid "" +"In order not to affect your normal work, please contact the administrator " +"for confirmation." +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:7 +msgid "Your password will expire in" +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:8 +msgid "" +"For your account security, please click on the link below to update your " +"password in time" +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:11 +msgid "Click here update password" +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:16 +msgid "If your password has expired, please click the link below to" +msgstr "" + +#: users/templates/users/_msg_reset_mfa.html:7 +msgid "Your MFA has been reset by site administrator" +msgstr "" + +#: users/templates/users/_msg_reset_mfa.html:8 +#: users/templates/users/_msg_reset_ssh_key.html:8 +msgid "Please click the link below to set" +msgstr "" + +#: users/templates/users/_msg_reset_mfa.html:11 +#: users/templates/users/_msg_reset_ssh_key.html:11 +msgid "Click here set" +msgstr "" + +#: users/templates/users/_msg_reset_ssh_key.html:7 +msgid "Your ssh public key has been reset by site administrator" +msgstr "" + +#: users/templates/users/_msg_user_created.html:15 +msgid "click here to set your password" +msgstr "" + +#: users/templates/users/forgot_password.html:46 +msgid "Input your email account, that will send a email to your" +msgstr "" + +#: users/templates/users/forgot_password.html:49 +msgid "" +"Enter your mobile number and a verification code will be sent to your phone" +msgstr "" + +#: users/templates/users/forgot_password.html:71 +msgid "Email account" +msgstr "" + +#: users/templates/users/forgot_password.html:93 +msgid "Mobile number" +msgstr "" + +#: users/templates/users/forgot_password.html:101 +msgid "Send" +msgstr "" + +#: users/templates/users/forgot_password.html:105 +#: users/templates/users/forgot_password_previewing.html:30 +msgid "Submit" +msgstr "" + +#: users/templates/users/forgot_password_previewing.html:21 +msgid "Please enter the username for which you want to retrieve the password" +msgstr "" + +#: users/templates/users/mfa_setting.html:24 +msgid "Enable MFA" +msgstr "" + +#: users/templates/users/mfa_setting.html:30 +msgid "MFA force enable, cannot disable" +msgstr "" + +#: users/templates/users/mfa_setting.html:48 +msgid "MFA setting" +msgstr "" + +#: users/templates/users/mfa_setting.html:61 +msgid "Reset" +msgstr "" + +#: users/templates/users/reset_password.html:23 +msgid "Your password must satisfy" +msgstr "" + +#: users/templates/users/reset_password.html:24 +msgid "Password strength" +msgstr "" + +#: users/templates/users/reset_password.html:48 +msgid "Very weak" +msgstr "" + +#: users/templates/users/reset_password.html:49 +msgid "Weak" +msgstr "" + +#: users/templates/users/reset_password.html:51 +msgid "Medium" +msgstr "" + +#: users/templates/users/reset_password.html:52 +msgid "Strong" +msgstr "" + +#: users/templates/users/reset_password.html:53 +msgid "Very strong" +msgstr "" + +#: users/templates/users/user_otp_check_password.html:6 +msgid "Enable OTP" +msgstr "" + +#: users/templates/users/user_otp_enable_bind.html:6 +msgid "Bind one-time password authenticator" +msgstr "" + +#: users/templates/users/user_otp_enable_bind.html:13 +msgid "" +"Use the MFA Authenticator application to scan the following qr code for a 6-" +"bit verification code" +msgstr "" + +#: users/templates/users/user_otp_enable_bind.html:22 +#: users/templates/users/user_verify_mfa.html:27 +msgid "Six figures" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:6 +msgid "Install app" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:13 +msgid "" +"Download and install the MFA Authenticator application on your phone or " +"applet of WeChat" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:18 +msgid "Android downloads" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:23 +msgid "iPhone downloads" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:27 +msgid "" +"After installation, click the next step to enter the binding page (if " +"installed, go to the next step directly)." +msgstr "" + +#: users/templates/users/user_password_verify.html:8 +#: users/templates/users/user_password_verify.html:9 +msgid "Verify password" +msgstr "" + +#: users/templates/users/user_verify_mfa.html:9 +msgid "Authenticate" +msgstr "" + +#: users/templates/users/user_verify_mfa.html:15 +msgid "" +"The account protection has been opened, please complete the following " +"operations according to the prompts" +msgstr "" + +#: users/templates/users/user_verify_mfa.html:17 +msgid "Open MFA Authenticator and enter the 6-bit dynamic code" +msgstr "" + +#: users/views/profile/otp.py:106 +msgid "Already bound" +msgstr "" + +#: users/views/profile/otp.py:107 +msgid "MFA already bound, disable first, then bound" +msgstr "" + +#: users/views/profile/otp.py:134 +msgid "OTP enable success" +msgstr "" + +#: users/views/profile/otp.py:135 +msgid "OTP enable success, return login page" +msgstr "" + +#: users/views/profile/otp.py:177 +msgid "Disable OTP" +msgstr "" + +#: users/views/profile/otp.py:183 +msgid "OTP disable success" +msgstr "" + +#: users/views/profile/otp.py:184 +msgid "OTP disable success, return login page" +msgstr "" + +#: users/views/profile/password.py:33 users/views/profile/password.py:38 +msgid "Password invalid" +msgstr "" + +#: users/views/profile/reset.py:66 +msgid "" +"Non-local users can log in only from third-party platforms and cannot change " +"their passwords: {}" +msgstr "" + +#: users/views/profile/reset.py:188 users/views/profile/reset.py:199 +msgid "Token invalid or expired" +msgstr "" + +#: users/views/profile/reset.py:204 +msgid "User auth from {}, go there change password" +msgstr "" + +#: users/views/profile/reset.py:211 +msgid "* Your password does not meet the requirements" +msgstr "" + +#: users/views/profile/reset.py:217 +msgid "* The new password cannot be the last {} passwords" +msgstr "" + +#: users/views/profile/reset.py:234 +msgid "Reset password success, return to login page" +msgstr "" + +#: xpack/apps.py:8 +msgid "XPACK" +msgstr "" + +#: xpack/exceptions.py:7 +msgid "" +"The current task is not synchronized with unmatched policy assets, skipping" +msgstr "" + +#: xpack/plugins/cloud/api.py:56 +msgid "Test connection successful" +msgstr "" + +#: xpack/plugins/cloud/api.py:58 +msgid "Test connection failed: {}" +msgstr "" + +#: xpack/plugins/cloud/const.py:8 +msgid "Alibaba Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:9 +msgid "AWS (International)" +msgstr "" + +#: xpack/plugins/cloud/const.py:10 +msgid "AWS (China)" +msgstr "" + +#: xpack/plugins/cloud/const.py:11 +msgid "Azure (China)" +msgstr "" + +#: xpack/plugins/cloud/const.py:12 +msgid "Azure (International)" +msgstr "" + +#: xpack/plugins/cloud/const.py:14 +msgid "Baidu Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:15 +msgid "JD Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:16 +msgid "KingSoft Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:17 +msgid "Tencent Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:18 +msgid "Tencent Cloud (Lighthouse)" +msgstr "" + +#: xpack/plugins/cloud/const.py:19 +msgid "Google Cloud Platform" +msgstr "" + +#: xpack/plugins/cloud/const.py:20 +msgid "UCloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:22 +msgid "VMware" +msgstr "" + +#: xpack/plugins/cloud/const.py:23 xpack/plugins/cloud/providers/nutanix.py:15 +msgid "Nutanix" +msgstr "" + +#: xpack/plugins/cloud/const.py:24 +msgid "Huawei Private Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:25 +msgid "Qingyun Private Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:26 +msgid "CTYun Private Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:27 +msgid "OpenStack" +msgstr "" + +#: xpack/plugins/cloud/const.py:28 xpack/plugins/cloud/providers/zstack.py:21 +msgid "ZStack" +msgstr "" + +#: xpack/plugins/cloud/const.py:29 +msgid "Fusion Compute" +msgstr "" + +#: xpack/plugins/cloud/const.py:30 +msgid "SCP" +msgstr "" + +#: xpack/plugins/cloud/const.py:31 +msgid "Apsara Stack" +msgstr "" + +#: xpack/plugins/cloud/const.py:36 +msgid "Private IP" +msgstr "" + +#: xpack/plugins/cloud/const.py:37 +msgid "Public IP" +msgstr "" + +#: xpack/plugins/cloud/const.py:41 xpack/plugins/cloud/models.py:303 +msgid "Instance name" +msgstr "" + +#: xpack/plugins/cloud/const.py:42 +msgid "Instance name and Partial IP" +msgstr "" + +#: xpack/plugins/cloud/const.py:47 +msgid "Succeed" +msgstr "" + +#: xpack/plugins/cloud/const.py:51 +msgid "Unsync" +msgstr "" + +#: xpack/plugins/cloud/const.py:52 +msgid "New Sync" +msgstr "" + +#: xpack/plugins/cloud/const.py:53 +msgid "Synced" +msgstr "" + +#: xpack/plugins/cloud/const.py:54 +msgid "Released" +msgstr "" + +#: xpack/plugins/cloud/const.py:58 +msgid "And" +msgstr "" + +#: xpack/plugins/cloud/const.py:59 +msgid "Or" +msgstr "" + +#: xpack/plugins/cloud/manager.py:56 +msgid "Account unavailable" +msgstr "" + +#: xpack/plugins/cloud/meta.py:9 +msgid "Cloud center" +msgstr "" + +#: xpack/plugins/cloud/models.py:34 +msgid "Provider" +msgstr "" + +#: xpack/plugins/cloud/models.py:37 +#: xpack/plugins/cloud/serializers/account.py:67 +msgid "Attrs" +msgstr "" + +#: xpack/plugins/cloud/models.py:38 +msgid "Validity" +msgstr "" + +#: xpack/plugins/cloud/models.py:43 +msgid "Cloud account" +msgstr "" + +#: xpack/plugins/cloud/models.py:45 +msgid "Test cloud account" +msgstr "" + +#: xpack/plugins/cloud/models.py:92 xpack/plugins/cloud/serializers/task.py:159 +msgid "Regions" +msgstr "" + +#: xpack/plugins/cloud/models.py:95 +msgid "Hostname strategy" +msgstr "" + +#: xpack/plugins/cloud/models.py:100 +#: xpack/plugins/cloud/serializers/task.py:162 +msgid "IP network segment group" +msgstr "" + +#: xpack/plugins/cloud/models.py:103 +#: xpack/plugins/cloud/serializers/task.py:167 +msgid "Sync IP type" +msgstr "" + +#: xpack/plugins/cloud/models.py:106 +#: xpack/plugins/cloud/serializers/task.py:185 +msgid "Always update" +msgstr "" + +#: xpack/plugins/cloud/models.py:108 +msgid "Fully synchronous" +msgstr "" + +#: xpack/plugins/cloud/models.py:113 +msgid "Date last sync" +msgstr "" + +#: xpack/plugins/cloud/models.py:116 xpack/plugins/cloud/models.py:321 +#: xpack/plugins/cloud/models.py:345 +msgid "Strategy" +msgstr "" + +#: xpack/plugins/cloud/models.py:121 xpack/plugins/cloud/models.py:200 +msgid "Sync instance task" +msgstr "" + +#: xpack/plugins/cloud/models.py:211 xpack/plugins/cloud/models.py:263 +msgid "Date sync" +msgstr "" + +#: xpack/plugins/cloud/models.py:215 +msgid "Sync instance snapshot" +msgstr "" + +#: xpack/plugins/cloud/models.py:219 +msgid "Sync instance task execution" +msgstr "" + +#: xpack/plugins/cloud/models.py:243 +msgid "Sync task" +msgstr "" + +#: xpack/plugins/cloud/models.py:247 +msgid "Sync instance task history" +msgstr "" + +#: xpack/plugins/cloud/models.py:250 +msgid "Instance" +msgstr "" + +#: xpack/plugins/cloud/models.py:267 +msgid "Sync instance detail" +msgstr "" + +#: xpack/plugins/cloud/models.py:279 xpack/plugins/cloud/serializers/task.py:72 +msgid "Rule relation" +msgstr "" + +#: xpack/plugins/cloud/models.py:288 +msgid "Task strategy" +msgstr "" + +#: xpack/plugins/cloud/models.py:292 +msgid "Equal" +msgstr "" + +#: xpack/plugins/cloud/models.py:293 +msgid "Not Equal" +msgstr "" + +#: xpack/plugins/cloud/models.py:294 +msgid "In" +msgstr "" + +#: xpack/plugins/cloud/models.py:295 +msgid "Contains" +msgstr "" + +#: xpack/plugins/cloud/models.py:296 +msgid "Exclude" +msgstr "" + +#: xpack/plugins/cloud/models.py:297 +msgid "Startswith" +msgstr "" + +#: xpack/plugins/cloud/models.py:298 +msgid "Endswith" +msgstr "" + +#: xpack/plugins/cloud/models.py:304 +msgid "Instance platform" +msgstr "" + +#: xpack/plugins/cloud/models.py:305 +msgid "Instance address" +msgstr "" + +#: xpack/plugins/cloud/models.py:312 +msgid "Rule attr" +msgstr "" + +#: xpack/plugins/cloud/models.py:316 +msgid "Rule match" +msgstr "" + +#: xpack/plugins/cloud/models.py:318 +msgid "Rule value" +msgstr "" + +#: xpack/plugins/cloud/models.py:325 xpack/plugins/cloud/serializers/task.py:75 +msgid "Strategy rule" +msgstr "" + +#: xpack/plugins/cloud/models.py:340 +msgid "Action attr" +msgstr "" + +#: xpack/plugins/cloud/models.py:342 +msgid "Action value" +msgstr "" + +#: xpack/plugins/cloud/models.py:349 xpack/plugins/cloud/serializers/task.py:78 +msgid "Strategy action" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:18 +msgid "China (Beijing)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:19 +msgid "China (Ningxia)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:22 +msgid "US East (Ohio)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:23 +msgid "US East (N. Virginia)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:24 +msgid "US West (N. California)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:25 +msgid "US West (Oregon)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:26 +msgid "Africa (Cape Town)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:27 +msgid "Asia Pacific (Hong Kong)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:28 +msgid "Asia Pacific (Mumbai)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:29 +msgid "Asia Pacific (Osaka-Local)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:30 +msgid "Asia Pacific (Seoul)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:31 +msgid "Asia Pacific (Singapore)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:32 +msgid "Asia Pacific (Sydney)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:33 +msgid "Asia Pacific (Tokyo)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:34 +msgid "Canada (Central)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:35 +msgid "Europe (Frankfurt)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:36 +msgid "Europe (Ireland)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:37 +msgid "Europe (London)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:38 +msgid "Europe (Milan)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:39 +msgid "Europe (Paris)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:40 +msgid "Europe (Stockholm)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:41 +msgid "Middle East (Bahrain)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:42 +msgid "South America (São Paulo)" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:54 +#: xpack/plugins/cloud/providers/jdcloud.py:125 +msgid "CN North-Beijing" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:55 +#: xpack/plugins/cloud/providers/huaweicloud.py:42 +#: xpack/plugins/cloud/providers/jdcloud.py:128 +msgid "CN South-Guangzhou" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:56 +msgid "CN East-Suzhou" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:57 +#: xpack/plugins/cloud/providers/huaweicloud.py:49 +msgid "CN-Hong Kong" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:58 +msgid "CN Center-Wuhan" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:59 +msgid "CN North-Baoding" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:60 +#: xpack/plugins/cloud/providers/jdcloud.py:127 +msgid "CN East-Shanghai" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:61 +#: xpack/plugins/cloud/providers/huaweicloud.py:51 +msgid "AP-Singapore" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:39 +msgid "CN North-Beijing1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:40 +msgid "CN North-Beijing4" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:41 +msgid "CN North-Ulanqab1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:43 +msgid "CN South-Shenzhen" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:44 +msgid "CN South-Guangzhou-InvitationOnly" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:45 +msgid "CN East-Shanghai2" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:46 +msgid "CN East-Shanghai1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:48 +msgid "CN Southwest-Guiyang1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:50 +msgid "AP-Bangkok" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:53 +msgid "AF-Johannesburg" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:54 +msgid "LA-Mexico City1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:55 +msgid "LA-Santiago" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:56 +msgid "LA-Sao Paulo1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:58 +msgid "TR-Istanbul" +msgstr "" + +#: xpack/plugins/cloud/providers/jdcloud.py:126 +msgid "CN East-Suqian" +msgstr "" + +#: xpack/plugins/cloud/serializers/account.py:68 +msgid "Validity display" +msgstr "" + +#: xpack/plugins/cloud/serializers/account.py:69 +msgid "Provider display" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:17 +msgid "Access key id" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:35 +msgid "Client ID" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:41 +msgid "Tenant ID" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:44 +msgid "Subscription ID" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:98 +#: xpack/plugins/cloud/serializers/account_attrs.py:102 +#: xpack/plugins/cloud/serializers/account_attrs.py:126 +#: xpack/plugins/cloud/serializers/account_attrs.py:156 +#: xpack/plugins/cloud/serializers/account_attrs.py:206 +msgid "API Endpoint" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:108 +msgid "Auth url" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:109 +msgid "eg: http://openstack.example.com:5000/v3" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:112 +msgid "User domain" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:127 +msgid "Cert File" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:128 +msgid "Key File" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:144 +msgid "Service account key" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:145 +msgid "The file is in JSON format" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:163 +msgid "IP address invalid `{}`, {}" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:179 +msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:182 +msgid "" +"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 " +"synchronized.
If the port is 0, all IP addresses are valid." +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:190 +msgid "Hostname prefix" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:193 +msgid "IP segment" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:197 +msgid "Test port" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:200 +msgid "Test timeout" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:216 +msgid "Project" +msgstr "" + +#: xpack/plugins/cloud/serializers/task.py:151 +msgid "" +"Only instances matching the IP range will be synced.
If the instance " +"contains multiple IP addresses, the first IP address that matches will be " +"used as the IP for the created asset.
The default value of * means sync " +"all instances and randomly match IP addresses.
Such as: 192.168.1.0/24, " +"10.1.1.1-10.1.1.20" +msgstr "" + +#: xpack/plugins/cloud/serializers/task.py:157 +msgid "History count" +msgstr "" + +#: xpack/plugins/cloud/serializers/task.py:158 +msgid "Instance count" +msgstr "" + +#: xpack/plugins/cloud/tasks.py:27 +msgid "Run sync instance task" +msgstr "" + +#: xpack/plugins/cloud/tasks.py:41 +msgid "Period clean sync instance task execution" +msgstr "" + +#: xpack/plugins/interface/api.py:52 +msgid "Restore default successfully." +msgstr "" + +#: xpack/plugins/interface/meta.py:9 +msgid "Interface settings" +msgstr "" + +#: xpack/plugins/interface/models.py:23 +msgid "Login title" +msgstr "" + +#: xpack/plugins/interface/models.py:27 +msgid "Login image" +msgstr "" + +#: xpack/plugins/interface/models.py:31 +msgid "Website icon" +msgstr "" + +#: xpack/plugins/interface/models.py:35 +msgid "Index logo" +msgstr "" + +#: xpack/plugins/interface/models.py:39 +msgid "Logout logo" +msgstr "" + +#: xpack/plugins/interface/models.py:41 +#: xpack/plugins/interface/serializers/interface.py:26 +msgid "Theme" +msgstr "" + +#: xpack/plugins/interface/models.py:42 +msgid "Beian link" +msgstr "" + +#: xpack/plugins/interface/models.py:43 +msgid "Beian text" +msgstr "" + +#: xpack/plugins/interface/models.py:46 xpack/plugins/interface/models.py:87 +msgid "Interface setting" +msgstr "" + +#: xpack/plugins/interface/serializers/interface.py:37 +msgid "Wide logo on top" +msgstr "" + +#: xpack/plugins/interface/serializers/interface.py:38 +msgid "Small logo without text" +msgstr "" + +#: xpack/plugins/license/api.py:52 +msgid "License import successfully" +msgstr "" + +#: xpack/plugins/license/api.py:53 +msgid "License is invalid" +msgstr "" + +#: xpack/plugins/license/meta.py:10 xpack/plugins/license/models.py:144 +msgid "License" +msgstr "" + +#: xpack/plugins/license/models.py:80 +msgid "Basic edition" +msgstr "" + +#: xpack/plugins/license/models.py:82 +msgid "Standard edition" +msgstr "" + +#: xpack/plugins/license/models.py:84 +msgid "Professional edition" +msgstr "" + +#: xpack/plugins/license/models.py:86 +msgid "Ultimate edition" +msgstr "" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo new file mode 100644 index 000000000..ae3f5212a --- /dev/null +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5170906f3d80c41be1f8843b6c6823a019e28e8f21f437c4f75d3b03ed8c8249 +size 337 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po new file mode 100644 index 000000000..e23fc06f3 --- /dev/null +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -0,0 +1,9036 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-05-10 19:19+0800\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: accounts/api/automations/base.py:79 tickets/api/ticket.py:132 +msgid "The parameter 'action' must be [{}]" +msgstr "" + +#: accounts/automations/change_secret/manager.py:225 +#, python-format +msgid "Success: %s, Failed: %s, Total: %s" +msgstr "" + +#: accounts/const/account.py:6 +#: accounts/serializers/automations/change_secret.py:34 +#: audits/signal_handlers/login_log.py:34 authentication/confirm/password.py:9 +#: authentication/confirm/password.py:24 authentication/confirm/password.py:26 +#: authentication/forms.py:28 +#: authentication/templates/authentication/login.html:329 +#: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 +#: settings/serializers/msg.py:35 terminal/serializers/storage.py:123 +#: terminal/serializers/storage.py:142 users/forms/profile.py:21 +#: users/serializers/user.py:110 +#: users/templates/users/_msg_user_created.html:13 +#: users/templates/users/user_password_verify.html:18 +#: xpack/plugins/cloud/serializers/account_attrs.py:28 +msgid "Password" +msgstr "" + +#: accounts/const/account.py:7 +#: accounts/serializers/automations/change_secret.py:35 +#: terminal/serializers/storage.py:124 +msgid "SSH key" +msgstr "" + +#: accounts/const/account.py:8 authentication/models/access_key.py:42 +msgid "Access key" +msgstr "" + +#: accounts/const/account.py:9 authentication/backends/passkey/models.py:16 +#: authentication/models/sso_token.py:14 settings/serializers/feature.py:52 +msgid "Token" +msgstr "" + +#: accounts/const/account.py:10 +msgid "API key" +msgstr "" + +#: accounts/const/account.py:14 common/db/fields.py:235 +#: settings/serializers/terminal.py:14 +msgid "All" +msgstr "" + +#: accounts/const/account.py:15 accounts/models/virtual.py:26 +msgid "Manual input" +msgstr "" + +#: accounts/const/account.py:16 +msgid "Dynamic user" +msgstr "" + +#: accounts/const/account.py:17 +msgid "Anonymous account" +msgstr "" + +#: accounts/const/account.py:18 +msgid "Specified account" +msgstr "" + +#: accounts/const/account.py:26 users/models/user.py:751 +msgid "Local" +msgstr "" + +#: accounts/const/account.py:27 +msgid "Collected" +msgstr "" + +#: accounts/const/account.py:28 accounts/serializers/account/account.py:28 +#: settings/serializers/auth/sms.py:79 +msgid "Template" +msgstr "" + +#: accounts/const/account.py:32 ops/const.py:46 +msgid "Skip" +msgstr "" + +#: accounts/const/account.py:33 audits/const.py:24 rbac/tree.py:239 +#: templates/_csv_import_export.html:18 templates/_csv_update_modal.html:6 +msgid "Update" +msgstr "" + +#: accounts/const/account.py:34 accounts/const/automation.py:109 +#: accounts/serializers/automations/change_secret.py:164 audits/const.py:62 +#: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 +#: ops/const.py:76 terminal/const.py:79 xpack/plugins/cloud/const.py:46 +msgid "Failed" +msgstr "" + +#: accounts/const/automation.py:24 rbac/tree.py:52 +msgid "Push account" +msgstr "" + +#: accounts/const/automation.py:25 +msgid "Change secret" +msgstr "" + +#: accounts/const/automation.py:26 +msgid "Verify account" +msgstr "" + +#: accounts/const/automation.py:27 accounts/tasks/remove_account.py:24 +#: accounts/tasks/remove_account.py:33 +msgid "Remove account" +msgstr "" + +#: accounts/const/automation.py:28 +msgid "Gather accounts" +msgstr "" + +#: accounts/const/automation.py:29 +msgid "Verify gateway account" +msgstr "" + +#: accounts/const/automation.py:47 +msgid "Specific secret" +msgstr "" + +#: accounts/const/automation.py:48 +msgid "Random generate" +msgstr "" + +#: accounts/const/automation.py:52 ops/const.py:13 +msgid "Append SSH KEY" +msgstr "" + +#: accounts/const/automation.py:53 ops/const.py:14 +msgid "Empty and append SSH KEY" +msgstr "" + +#: accounts/const/automation.py:54 ops/const.py:15 +msgid "Replace (Replace only keys pushed by JumpServer) " +msgstr "" + +#: accounts/const/automation.py:59 +msgid "On asset create" +msgstr "" + +#: accounts/const/automation.py:62 +msgid "On perm add user" +msgstr "" + +#: accounts/const/automation.py:64 +msgid "On perm add user group" +msgstr "" + +#: accounts/const/automation.py:66 +msgid "On perm add asset" +msgstr "" + +#: accounts/const/automation.py:68 +msgid "On perm add node" +msgstr "" + +#: accounts/const/automation.py:70 +msgid "On perm add account" +msgstr "" + +#: accounts/const/automation.py:72 +msgid "On asset join node" +msgstr "" + +#: accounts/const/automation.py:74 +msgid "On user join group" +msgstr "" + +#: accounts/const/automation.py:82 +msgid "On perm change" +msgstr "" + +#: accounts/const/automation.py:89 +msgid "Inherit from group or node" +msgstr "" + +#: accounts/const/automation.py:97 +msgid "Create and push" +msgstr "" + +#: accounts/const/automation.py:98 +msgid "Only create" +msgstr "" + +#: accounts/const/automation.py:103 +#: authentication/serializers/password_mfa.py:16 +#: authentication/serializers/password_mfa.py:24 +#: notifications/backends/__init__.py:10 settings/serializers/msg.py:22 +#: settings/serializers/msg.py:64 users/forms/profile.py:100 +#: users/forms/profile.py:108 users/models/user.py:876 +#: users/templates/users/forgot_password.html:162 +#: users/views/profile/reset.py:94 +msgid "Email" +msgstr "" + +#: accounts/const/automation.py:105 terminal/const.py:87 +msgid "SFTP" +msgstr "" + +#: accounts/const/automation.py:110 +#: accounts/serializers/automations/change_secret.py:163 audits/const.py:61 +#: audits/models.py:64 audits/signal_handlers/activity_log.py:33 +#: common/const/choices.py:18 ops/const.py:74 ops/serializers/celery.py:48 +#: terminal/const.py:78 terminal/models/session/sharing.py:121 +#: tickets/views/approve.py:128 +msgid "Success" +msgstr "" + +#: accounts/const/automation.py:111 common/const/choices.py:16 +#: terminal/const.py:77 tickets/const.py:29 tickets/const.py:38 +msgid "Pending" +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 settings/serializers/feature.py:43 +msgid "HCP Vault" +msgstr "" + +#: accounts/mixins.py:35 +msgid "Export all" +msgstr "" + +#: accounts/mixins.py:37 +msgid "Export only selected items" +msgstr "" + +#: accounts/mixins.py:42 +#, python-format +msgid "Export filtered: %s" +msgstr "" + +#: accounts/mixins.py:48 +#, python-format +msgid "User %s view/export secret" +msgstr "" + +#: accounts/models/account.py:49 +#: accounts/models/automations/gather_account.py:16 +#: accounts/serializers/account/account.py:215 +#: accounts/serializers/account/account.py:260 +#: accounts/serializers/account/gathered_account.py:10 +#: accounts/serializers/automations/change_secret.py:108 +#: accounts/serializers/automations/change_secret.py:140 +#: accounts/templates/accounts/asset_account_change_info.html:7 +#: accounts/templates/accounts/change_secret_failed_info.html:11 +#: acls/serializers/base.py:123 assets/models/asset/common.py:95 +#: assets/models/asset/common.py:349 assets/models/cmd_filter.py:36 +#: audits/models.py:58 authentication/models/connection_token.py:36 +#: perms/models/asset_permission.py:69 terminal/backends/command/models.py:17 +#: terminal/models/session/session.py:32 terminal/notifications.py:155 +#: terminal/serializers/command.py:17 terminal/serializers/session.py:28 +#: terminal/templates/terminal/_msg_command_warning.html:4 +#: terminal/templates/terminal/_msg_session_sharing.html:4 +#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:256 +msgid "Asset" +msgstr "" + +#: accounts/models/account.py:53 accounts/models/template.py:16 +#: accounts/serializers/account/account.py:222 +#: accounts/serializers/account/account.py:270 +#: accounts/serializers/account/template.py:27 +#: authentication/serializers/connect_token_secret.py:50 +msgid "Su from" +msgstr "" + +#: accounts/models/account.py:55 assets/const/protocol.py:177 +#: settings/serializers/auth/cas.py:20 terminal/models/applet/applet.py:35 +#: terminal/models/virtualapp/virtualapp.py:21 +msgid "Version" +msgstr "" + +#: accounts/models/account.py:57 accounts/serializers/account/account.py:217 +#: users/models/user.py:928 +msgid "Source" +msgstr "" + +#: accounts/models/account.py:58 +msgid "Source ID" +msgstr "" + +#: accounts/models/account.py:61 +#: accounts/serializers/automations/change_secret.py:110 +#: accounts/serializers/automations/change_secret.py:141 +#: accounts/templates/accounts/change_secret_failed_info.html:12 +#: acls/serializers/base.py:124 acls/templates/acls/asset_login_reminder.html:7 +#: assets/serializers/gateway.py:28 audits/models.py:59 +#: authentication/api/connection_token.py:411 ops/models/base.py:18 +#: perms/models/asset_permission.py:75 settings/serializers/msg.py:33 +#: terminal/backends/command/models.py:18 terminal/models/session/session.py:34 +#: terminal/serializers/command.py:72 +#: terminal/templates/terminal/_msg_command_warning.html:8 +#: terminal/templates/terminal/_msg_session_sharing.html:8 +#: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:89 +msgid "Account" +msgstr "" + +#: accounts/models/account.py:67 +msgid "Can view asset account secret" +msgstr "" + +#: accounts/models/account.py:68 +msgid "Can view asset history account" +msgstr "" + +#: accounts/models/account.py:69 +msgid "Can view asset history account secret" +msgstr "" + +#: accounts/models/account.py:70 +msgid "Can verify account" +msgstr "" + +#: accounts/models/account.py:71 +msgid "Can push account" +msgstr "" + +#: accounts/models/account.py:72 +msgid "Can remove account" +msgstr "" + +#: accounts/models/automations/backup_account.py:27 +msgid "Backup type" +msgstr "" + +#: accounts/models/automations/backup_account.py:28 +#: accounts/models/automations/backup_account.py:29 +msgid "Password divided" +msgstr "" + +#: accounts/models/automations/backup_account.py:32 +msgid "Recipient part one" +msgstr "" + +#: accounts/models/automations/backup_account.py:36 +msgid "Recipient part two" +msgstr "" + +#: accounts/models/automations/backup_account.py:40 +msgid "Object storage recipient part one" +msgstr "" + +#: accounts/models/automations/backup_account.py:44 +msgid "Object storage recipient part two" +msgstr "" + +#: accounts/models/automations/backup_account.py:47 +msgid "Zip encrypt password" +msgstr "" + +#: accounts/models/automations/backup_account.py:56 +#: accounts/models/automations/backup_account.py:139 +msgid "Account backup plan" +msgstr "" + +#: accounts/models/automations/backup_account.py:120 +#: assets/models/automations/base.py:115 audits/models.py:65 +#: ops/models/base.py:55 ops/models/celery.py:88 ops/models/job.py:241 +#: ops/templates/ops/celery_task_log.html:75 +#: perms/models/asset_permission.py:78 +#: settings/templates/ldap/_msg_import_ldap_user.html:5 +#: terminal/models/applet/host.py:141 terminal/models/session/session.py:45 +#: tickets/models/ticket/apply_application.py:30 +#: tickets/models/ticket/apply_asset.py:19 +msgid "Date start" +msgstr "" + +#: accounts/models/automations/backup_account.py:123 +#: authentication/templates/authentication/_msg_oauth_bind.html:11 +#: notifications/notifications.py:186 +#: settings/templates/ldap/_msg_import_ldap_user.html:3 +msgid "Time" +msgstr "" + +#: accounts/models/automations/backup_account.py:127 +msgid "Account backup snapshot" +msgstr "" + +#: accounts/models/automations/backup_account.py:131 +#: accounts/serializers/account/backup.py:48 +#: accounts/serializers/automations/base.py:56 +#: assets/models/automations/base.py:122 +#: assets/serializers/automations/base.py:39 +msgid "Trigger mode" +msgstr "" + +#: accounts/models/automations/backup_account.py:134 audits/models.py:203 +#: terminal/models/session/sharing.py:125 xpack/plugins/cloud/models.py:208 +msgid "Reason" +msgstr "" + +#: accounts/models/automations/backup_account.py:136 +#: accounts/serializers/automations/change_secret.py:107 +#: accounts/serializers/automations/change_secret.py:142 +#: ops/serializers/job.py:74 terminal/serializers/session.py:52 +msgid "Is success" +msgstr "" + +#: accounts/models/automations/backup_account.py:144 +msgid "Account backup execution" +msgstr "" + +#: accounts/models/automations/base.py:18 +msgid "Account automation task" +msgstr "" + +#: accounts/models/automations/base.py:32 +msgid "Automation execution" +msgstr "" + +#: accounts/models/automations/base.py:33 +msgid "Automation executions" +msgstr "" + +#: accounts/models/automations/base.py:35 +msgid "Can view change secret execution" +msgstr "" + +#: accounts/models/automations/base.py:36 +msgid "Can add change secret execution" +msgstr "" + +#: accounts/models/automations/base.py:38 +msgid "Can view gather accounts execution" +msgstr "" + +#: accounts/models/automations/base.py:39 +msgid "Can add gather accounts execution" +msgstr "" + +#: accounts/models/automations/base.py:41 +msgid "Can view push account execution" +msgstr "" + +#: accounts/models/automations/base.py:42 +msgid "Can add push account execution" +msgstr "" + +#: accounts/models/automations/base.py:54 +msgid "SSH key change strategy" +msgstr "" + +#: accounts/models/automations/change_secret.py:15 +#: accounts/models/automations/gather_account.py:58 +#: accounts/serializers/account/backup.py:40 +#: accounts/serializers/automations/change_secret.py:58 +#: settings/serializers/auth/ldap.py:90 +msgid "Recipient" +msgstr "" + +#: accounts/models/automations/change_secret.py:22 +msgid "Change secret automation" +msgstr "" + +#: accounts/models/automations/change_secret.py:39 +msgid "Old secret" +msgstr "" + +#: accounts/models/automations/change_secret.py:40 +msgid "New secret" +msgstr "" + +#: accounts/models/automations/change_secret.py:41 +msgid "Date started" +msgstr "" + +#: accounts/models/automations/change_secret.py:42 +#: assets/models/automations/base.py:116 ops/models/base.py:56 +#: ops/models/celery.py:89 ops/models/job.py:242 +#: terminal/models/applet/host.py:142 +msgid "Date finished" +msgstr "" + +#: accounts/models/automations/change_secret.py:44 +#: assets/models/automations/base.py:113 audits/models.py:208 +#: audits/serializers.py:54 ops/models/base.py:49 ops/models/job.py:233 +#: terminal/models/applet/applet.py:320 terminal/models/applet/host.py:140 +#: terminal/models/component/status.py:30 +#: terminal/models/virtualapp/virtualapp.py:99 +#: terminal/serializers/applet.py:18 terminal/serializers/applet_host.py:136 +#: terminal/serializers/virtualapp.py:35 tickets/models/ticket/general.py:281 +#: tickets/serializers/super_ticket.py:13 +#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:204 +#: xpack/plugins/cloud/models.py:260 +msgid "Status" +msgstr "" + +#: accounts/models/automations/change_secret.py:47 +#: accounts/serializers/account/account.py:262 +#: accounts/templates/accounts/change_secret_failed_info.html:13 +#: assets/const/automation.py:8 +#: authentication/templates/authentication/passkey.html:173 +#: authentication/views/base.py:42 authentication/views/base.py:43 +#: authentication/views/base.py:44 common/const/choices.py:20 +#: settings/templates/ldap/_msg_import_ldap_user.html:26 +msgid "Error" +msgstr "" + +#: accounts/models/automations/change_secret.py:51 +msgid "Change secret record" +msgstr "" + +#: accounts/models/automations/gather_account.py:14 +msgid "Present" +msgstr "" + +#: accounts/models/automations/gather_account.py:15 +msgid "Date login" +msgstr "" + +#: accounts/models/automations/gather_account.py:17 +#: accounts/models/automations/push_account.py:15 accounts/models/base.py:65 +#: accounts/serializers/account/virtual.py:21 acls/serializers/base.py:19 +#: acls/serializers/base.py:50 audits/models.py:188 authentication/forms.py:21 +#: authentication/forms.py:23 authentication/models/temp_token.py:9 +#: authentication/templates/authentication/_msg_different_city.html:9 +#: authentication/templates/authentication/_msg_oauth_bind.html:9 +#: terminal/serializers/storage.py:136 users/forms/profile.py:31 +#: users/forms/profile.py:114 users/models/user.py:872 +#: users/templates/users/_msg_user_created.html:12 +#: xpack/plugins/cloud/serializers/account_attrs.py:26 +msgid "Username" +msgstr "" + +#: accounts/models/automations/gather_account.py:18 +msgid "Address login" +msgstr "" + +#: accounts/models/automations/gather_account.py:44 +msgid "Gather account automation" +msgstr "" + +#: accounts/models/automations/gather_account.py:56 +msgid "Is sync account" +msgstr "" + +#: accounts/models/automations/gather_account.py:75 +#: accounts/tasks/gather_accounts.py:29 +msgid "Gather asset accounts" +msgstr "" + +#: accounts/models/automations/push_account.py:14 +msgid "Triggers" +msgstr "" + +#: accounts/models/automations/push_account.py:16 acls/models/base.py:41 +#: acls/serializers/base.py:57 assets/models/cmd_filter.py:81 +#: audits/models.py:92 audits/serializers.py:84 +#: authentication/serializers/connect_token_secret.py:119 +#: authentication/templates/authentication/_access_key_modal.html:34 +#: tickets/serializers/ticket/ticket.py:21 +msgid "Action" +msgstr "" + +#: accounts/models/automations/push_account.py:57 +msgid "Push asset account" +msgstr "" + +#: accounts/models/automations/verify_account.py:15 +msgid "Verify asset account" +msgstr "" + +#: accounts/models/base.py:37 accounts/models/base.py:67 +#: accounts/serializers/account/account.py:442 +#: accounts/serializers/account/base.py:17 +#: accounts/serializers/automations/change_secret.py:47 +#: authentication/serializers/connect_token_secret.py:42 +#: authentication/serializers/connect_token_secret.py:51 +#: terminal/serializers/storage.py:140 +msgid "Secret type" +msgstr "" + +#: accounts/models/base.py:39 accounts/models/mixins/vault.py:49 +#: accounts/serializers/account/base.py:20 +#: authentication/models/temp_token.py:10 +#: authentication/templates/authentication/_access_key_modal.html:31 +#: settings/serializers/auth/radius.py:19 +msgid "Secret" +msgstr "" + +#: accounts/models/base.py:42 +#: accounts/serializers/automations/change_secret.py:41 +msgid "Secret strategy" +msgstr "" + +#: accounts/models/base.py:44 accounts/serializers/account/template.py:24 +#: accounts/serializers/automations/change_secret.py:46 +msgid "Password rules" +msgstr "" + +#: accounts/models/base.py:64 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 assets/models/asset/common.py:93 +#: assets/models/asset/common.py:159 assets/models/cmd_filter.py:21 +#: assets/models/domain.py:19 assets/models/label.py:18 +#: assets/models/platform.py:15 assets/models/platform.py:94 +#: assets/serializers/asset/common.py:149 assets/serializers/platform.py:143 +#: assets/serializers/platform.py:261 +#: authentication/backends/passkey/models.py:10 +#: authentication/serializers/connect_token_secret.py:113 +#: authentication/serializers/connect_token_secret.py:169 labels/models.py:11 +#: ops/mixin.py:21 ops/models/adhoc.py:20 ops/models/celery.py:15 +#: ops/models/celery.py:80 ops/models/job.py:142 ops/models/playbook.py:28 +#: ops/serializers/job.py:18 orgs/models.py:82 +#: perms/models/asset_permission.py:61 rbac/models/role.py:29 +#: settings/models.py:34 settings/models.py:183 settings/serializers/msg.py:89 +#: settings/serializers/terminal.py:9 terminal/models/applet/applet.py:33 +#: terminal/models/component/endpoint.py:12 +#: terminal/models/component/endpoint.py:109 +#: terminal/models/component/storage.py:26 terminal/models/component/task.py:13 +#: terminal/models/component/terminal.py:85 +#: terminal/models/virtualapp/provider.py:10 +#: terminal/models/virtualapp/virtualapp.py:19 tickets/api/ticket.py:87 +#: users/forms/profile.py:32 users/models/group.py:13 +#: users/models/preference.py:11 users/models/user.py:874 +#: xpack/plugins/cloud/models.py:32 xpack/plugins/cloud/models.py:276 +#: xpack/plugins/cloud/serializers/task.py:70 +msgid "Name" +msgstr "" + +#: accounts/models/base.py:69 +msgid "Privileged" +msgstr "" + +#: accounts/models/base.py:70 assets/models/asset/common.py:165 +#: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 +#: assets/models/label.py:22 +#: authentication/serializers/connect_token_secret.py:117 +#: terminal/models/applet/applet.py:40 +#: terminal/models/component/endpoint.py:120 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:180 +msgid "Is active" +msgstr "" + +#: accounts/models/template.py:18 +msgid "Auto push" +msgstr "" + +#: accounts/models/template.py:21 +msgid "Platforms" +msgstr "" + +#: accounts/models/template.py:23 +msgid "Push params" +msgstr "" + +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:333 +msgid "Account template" +msgstr "" + +#: accounts/models/template.py:31 +msgid "Can view asset account template secret" +msgstr "" + +#: accounts/models/template.py:32 +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 "" + +#: accounts/notifications.py:12 accounts/notifications.py:37 +msgid "Notification of account backup route task results" +msgstr "" + +#: accounts/notifications.py:22 accounts/notifications.py:46 +msgid "" +"{} - The account backup passage task has been completed. See the attachment " +"for details" +msgstr "" + +#: accounts/notifications.py:25 +msgid "" +"{} - The account backup passage task has been completed: the encryption " +"password has not been set - please go to personal information -> Basic file " +"encryption password for preference settings" +msgstr "" + +#: accounts/notifications.py:56 +msgid "Notification of implementation result of encryption change plan" +msgstr "" + +#: accounts/notifications.py:67 +msgid "" +"{} - The encryption change task has been completed. See the attachment for " +"details" +msgstr "" + +#: accounts/notifications.py:71 +msgid "" +"{} - The encryption change task has been completed: the encryption password " +"has not been set - please go to personal information -> set encryption " +"password in preferences" +msgstr "" + +#: accounts/notifications.py:83 +#: accounts/templates/accounts/asset_account_change_info.html:3 +msgid "Gather account change information" +msgstr "" + +#: accounts/notifications.py:105 +msgid "Change secret or push account failed information" +msgstr "" + +#: accounts/serializers/account/account.py:31 +msgid "Push now" +msgstr "" + +#: accounts/serializers/account/account.py:36 +msgid "Params" +msgstr "" + +#: accounts/serializers/account/account.py:40 +msgid "Exist policy" +msgstr "" + +#: accounts/serializers/account/account.py:195 assets/models/label.py:21 +#: assets/models/platform.py:95 assets/serializers/asset/common.py:125 +#: assets/serializers/cagegory.py:12 assets/serializers/platform.py:165 +#: assets/serializers/platform.py:262 perms/serializers/user_permission.py:26 +#: settings/models.py:36 tickets/models/ticket/apply_application.py:13 +#: users/models/preference.py:12 +msgid "Category" +msgstr "" + +#: accounts/serializers/account/account.py:196 +#: accounts/serializers/automations/base.py:55 acls/models/command_acl.py:24 +#: acls/serializers/command_acl.py:19 assets/models/automations/base.py:20 +#: assets/models/cmd_filter.py:74 assets/models/platform.py:96 +#: assets/serializers/asset/common.py:126 assets/serializers/platform.py:145 +#: assets/serializers/platform.py:164 audits/serializers.py:53 +#: audits/serializers.py:170 +#: authentication/serializers/connect_token_secret.py:126 ops/models/job.py:150 +#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:39 +#: terminal/models/component/storage.py:57 +#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29 +#: terminal/serializers/session.py:23 terminal/serializers/storage.py:264 +#: terminal/serializers/storage.py:276 tickets/models/comment.py:26 +#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16 +#: tickets/models/ticket/general.py:273 tickets/serializers/flow.py:53 +#: tickets/serializers/ticket/ticket.py:19 +msgid "Type" +msgstr "" + +#: accounts/serializers/account/account.py:211 +msgid "Asset not found" +msgstr "" + +#: accounts/serializers/account/account.py:251 +msgid "Has secret" +msgstr "" + +#: accounts/serializers/account/account.py:261 ops/models/celery.py:83 +#: tickets/models/comment.py:13 tickets/models/ticket/general.py:46 +#: tickets/models/ticket/general.py:277 tickets/serializers/super_ticket.py:14 +msgid "State" +msgstr "" + +#: accounts/serializers/account/account.py:263 +msgid "Changed" +msgstr "" + +#: accounts/serializers/account/account.py:273 +#: accounts/serializers/automations/base.py:22 acls/models/base.py:97 +#: acls/templates/acls/asset_login_reminder.html:6 +#: assets/models/automations/base.py:19 +#: assets/serializers/automations/base.py:20 +#: authentication/api/connection_token.py:410 ops/models/base.py:17 +#: ops/models/job.py:152 ops/serializers/job.py:19 +#: perms/serializers/permission.py:36 +#: terminal/templates/terminal/_msg_command_execute_alert.html:16 +msgid "Assets" +msgstr "" + +#: accounts/serializers/account/account.py:328 +msgid "Account already exists" +msgstr "" + +#: accounts/serializers/account/account.py:378 +#, python-format +msgid "Asset does not support this secret type: %s" +msgstr "" + +#: accounts/serializers/account/account.py:410 +msgid "Account has exist" +msgstr "" + +#: accounts/serializers/account/account.py:443 +#: authentication/serializers/connect_token_secret.py:159 +#: authentication/templates/authentication/_access_key_modal.html:30 +#: perms/models/perm_node.py:21 users/serializers/group.py:33 +msgid "ID" +msgstr "" + +#: accounts/serializers/account/account.py:453 acls/serializers/base.py:116 +#: acls/templates/acls/asset_login_reminder.html:5 +#: acls/templates/acls/user_login_reminder.html:5 +#: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:54 +#: audits/models.py:90 audits/models.py:172 audits/models.py:269 +#: audits/serializers.py:171 authentication/models/connection_token.py:32 +#: authentication/models/sso_token.py:16 +#: notifications/models/notification.py:12 +#: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:63 +#: rbac/builtin.py:124 rbac/models/rolebinding.py:49 +#: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 +#: terminal/models/session/session.py:30 terminal/models/session/sharing.py:34 +#: terminal/notifications.py:156 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:1062 +#: users/models/user.py:1100 +msgid "User" +msgstr "" + +#: accounts/serializers/account/account.py:454 +#: authentication/templates/authentication/_access_key_modal.html:33 +#: terminal/notifications.py:158 terminal/notifications.py:207 +msgid "Date" +msgstr "" + +#: accounts/serializers/account/backup.py:20 +msgid "Zip Encrypt Password" +msgstr "" + +#: accounts/serializers/account/backup.py:38 +#: accounts/serializers/automations/base.py:38 +msgid "Executions" +msgstr "" + +#: accounts/serializers/account/backup.py:41 +#: accounts/serializers/automations/change_secret.py:59 +msgid "Currently only mail sending is supported" +msgstr "" + +#: accounts/serializers/account/backup.py:43 +msgid "Asset type" +msgstr "" + +#: accounts/serializers/account/base.py:25 terminal/serializers/storage.py:149 +msgid "Passphrase" +msgstr "" + +#: accounts/serializers/account/base.py:78 +#: assets/serializers/asset/common.py:384 +msgid "Spec info" +msgstr "" + +#: accounts/serializers/account/base.py:80 +msgid "" +"Tip: If no username is required for authentication, fill in `null`, If AD " +"account, like `username@domain`" +msgstr "" + +#: accounts/serializers/account/template.py:13 +msgid "Password length" +msgstr "" + +#: accounts/serializers/account/template.py:14 +#: settings/serializers/security.py:44 +msgid "Lowercase" +msgstr "" + +#: accounts/serializers/account/template.py:15 +#: settings/serializers/security.py:41 +msgid "Uppercase" +msgstr "" + +#: accounts/serializers/account/template.py:16 +msgid "Digit" +msgstr "" + +#: accounts/serializers/account/template.py:17 +msgid "Special symbol" +msgstr "" + +#: accounts/serializers/account/template.py:19 +msgid "Exclude symbol" +msgstr "" + +#: accounts/serializers/account/template.py:38 +msgid "Secret generation strategy for account creation" +msgstr "" + +#: accounts/serializers/account/template.py:39 +msgid "Whether to automatically push the account to the asset" +msgstr "" + +#: accounts/serializers/account/template.py:42 +msgid "" +"Associated platform, you can configure push parameters. If not associated, " +"default parameters will be used" +msgstr "" + +#: accounts/serializers/account/virtual.py:19 assets/models/cmd_filter.py:40 +#: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:26 +#: ops/models/job.py:158 ops/models/playbook.py:31 rbac/models/role.py:37 +#: settings/models.py:39 terminal/models/applet/applet.py:45 +#: terminal/models/applet/applet.py:321 terminal/models/applet/host.py:143 +#: terminal/models/component/endpoint.py:25 +#: terminal/models/component/endpoint.py:119 +#: terminal/models/session/session.py:47 +#: terminal/models/virtualapp/virtualapp.py:28 tickets/models/comment.py:32 +#: tickets/models/ticket/general.py:295 users/models/user.py:910 +#: xpack/plugins/cloud/models.py:39 xpack/plugins/cloud/models.py:110 +msgid "Comment" +msgstr "" + +#: accounts/serializers/account/virtual.py:24 +msgid "" +"Current only support login from AD/LDAP. Secret priority: Same account in " +"asset secret > Login secret > Manual input.
For security, please set " +"config CACHE_LOGIN_PASSWORD_ENABLED to true" +msgstr "" + +#: accounts/serializers/automations/base.py:23 +#: assets/models/asset/common.py:164 assets/serializers/asset/common.py:152 +#: assets/serializers/automations/base.py:21 perms/serializers/permission.py:37 +msgid "Nodes" +msgstr "" + +#: accounts/serializers/automations/base.py:24 +msgid "Periodic perform" +msgstr "" + +#: accounts/serializers/automations/base.py:45 +msgid "Name already exists" +msgstr "" + +#: accounts/serializers/automations/base.py:54 +#: assets/models/automations/base.py:118 +#: assets/serializers/automations/base.py:38 +msgid "Automation snapshot" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:44 +msgid "SSH Key strategy" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:81 +msgid "* Please enter the correct password length" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:85 +msgid "* Password length range 6-30 bits" +msgstr "" + +#: accounts/serializers/automations/change_secret.py:114 +#: assets/models/automations/base.py:127 +msgid "Automation task execution" +msgstr "" + +#: accounts/signal_handlers.py:47 +#, python-format +msgid "Push related accounts to assets: %s, by system" +msgstr "" + +#: accounts/signal_handlers.py:56 +#, python-format +msgid "Add account: %s" +msgstr "" + +#: accounts/signal_handlers.py:58 +#, python-format +msgid "Delete account: %s" +msgstr "" + +#: accounts/tasks/automation.py:25 +msgid "Account execute automation" +msgstr "" + +#: accounts/tasks/automation.py:51 accounts/tasks/automation.py:56 +msgid "Execute automation record" +msgstr "" + +#: accounts/tasks/backup_account.py:25 +msgid "Execute account backup plan" +msgstr "" + +#: accounts/tasks/gather_accounts.py:34 +msgid "Gather assets accounts" +msgstr "" + +#: accounts/tasks/push_account.py:15 accounts/tasks/push_account.py:23 +msgid "Push accounts to assets" +msgstr "" + +#: accounts/tasks/remove_account.py:44 +msgid "Clean historical accounts" +msgstr "" + +#: accounts/tasks/remove_account.py:76 +msgid "Remove historical accounts that are out of range." +msgstr "" + +#: accounts/tasks/template.py:11 +msgid "Template sync info to related accounts" +msgstr "" + +#: accounts/tasks/vault.py:31 +msgid "Sync secret to vault" +msgstr "" + +#: accounts/tasks/verify_account.py:49 +msgid "Verify asset account availability" +msgstr "" + +#: accounts/tasks/verify_account.py:55 +msgid "Verify accounts connectivity" +msgstr "" + +#: accounts/templates/accounts/asset_account_change_info.html:8 +msgid "Added account" +msgstr "" + +#: accounts/templates/accounts/asset_account_change_info.html:9 +msgid "Deleted account" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:3 +#: ops/templates/ops/celery_task_log.html:71 terminal/serializers/task.py:10 +msgid "Task name" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:4 +msgid "Task execution id" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:5 +#: acls/templates/acls/asset_login_reminder.html:3 +#: acls/templates/acls/user_login_reminder.html:3 +msgid "Respectful" +msgstr "" + +#: accounts/templates/accounts/change_secret_failed_info.html:6 +msgid "" +"Hello! The following is the failure of changing the password of your assets " +"or pushing the account. Please check and handle it in time." +msgstr "" + +#: accounts/utils.py:52 +msgid "" +"If the password starts with {{` and ends with }} `, then the password is not " +"allowed." +msgstr "" + +#: accounts/utils.py:59 +msgid "private key invalid or passphrase error" +msgstr "" + +#: acls/apps.py:7 +msgid "App Acls" +msgstr "" + +#: acls/const.py:6 audits/const.py:36 terminal/const.py:11 tickets/const.py:44 +#: tickets/templates/tickets/approve_check_password.html:47 +msgid "Reject" +msgstr "" + +#: acls/const.py:7 audits/const.py:33 terminal/const.py:9 +msgid "Accept" +msgstr "" + +#: acls/const.py:8 audits/const.py:34 +msgid "Review" +msgstr "" + +#: acls/const.py:9 +msgid "Warn" +msgstr "" + +#: acls/const.py:10 +msgid "Notify" +msgstr "" + +#: acls/models/base.py:37 assets/models/cmd_filter.py:76 +#: terminal/models/component/endpoint.py:112 xpack/plugins/cloud/models.py:282 +msgid "Priority" +msgstr "" + +#: acls/models/base.py:38 assets/models/cmd_filter.py:76 +#: terminal/models/component/endpoint.py:113 xpack/plugins/cloud/models.py:283 +msgid "1-100, the lower the value will be match first" +msgstr "" + +#: acls/models/base.py:42 assets/models/cmd_filter.py:86 +#: authentication/serializers/connect_token_secret.py:91 +msgid "Reviewers" +msgstr "" + +#: acls/models/base.py:43 authentication/models/access_key.py:25 +#: authentication/models/connection_token.py:53 +#: authentication/templates/authentication/_access_key_modal.html:32 +#: perms/models/asset_permission.py:82 terminal/models/session/sharing.py:29 +#: tickets/const.py:36 +msgid "Active" +msgstr "" + +#: acls/models/base.py:81 perms/serializers/permission.py:32 +#: users/models/preference.py:16 users/serializers/group.py:21 +#: users/serializers/user.py:311 +msgid "Users" +msgstr "" + +#: acls/models/base.py:98 assets/models/automations/base.py:17 +#: assets/models/cmd_filter.py:38 assets/serializers/asset/common.py:128 +#: perms/serializers/permission.py:45 perms/serializers/user_permission.py:75 +#: rbac/tree.py:35 +msgid "Accounts" +msgstr "" + +#: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 +#: ops/serializers/job.py:73 terminal/const.py:86 +#: terminal/models/session/session.py:43 terminal/serializers/command.py:18 +#: terminal/templates/terminal/_msg_command_alert.html:12 +#: terminal/templates/terminal/_msg_command_execute_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:23 +msgid "Command" +msgstr "" + +#: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 +#: xpack/plugins/cloud/models.py:299 +msgid "Regex" +msgstr "" + +#: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79 +#: settings/models.py:184 settings/serializers/feature.py:19 +#: settings/serializers/msg.py:78 xpack/plugins/license/models.py:30 +msgid "Content" +msgstr "" + +#: acls/models/command_acl.py:26 assets/models/cmd_filter.py:79 +msgid "One line one command" +msgstr "" + +#: acls/models/command_acl.py:27 assets/models/cmd_filter.py:80 +msgid "Ignore case" +msgstr "" + +#: acls/models/command_acl.py:33 acls/models/command_acl.py:97 +#: acls/serializers/command_acl.py:29 +#: authentication/serializers/connect_token_secret.py:88 +#: terminal/templates/terminal/_msg_command_warning.html:14 +msgid "Command group" +msgstr "" + +#: acls/models/command_acl.py:86 +msgid "The generated regular expression is incorrect: {}" +msgstr "" + +#: acls/models/command_acl.py:103 +#: terminal/templates/terminal/_msg_command_warning.html:12 +msgid "Command acl" +msgstr "" + +#: acls/models/command_acl.py:112 tickets/const.py:12 +msgid "Command confirm" +msgstr "" + +#: acls/models/connect_method.py:10 +msgid "Connect methods" +msgstr "" + +#: acls/models/connect_method.py:13 +msgid "Connect method acl" +msgstr "" + +#: acls/models/login_acl.py:11 acls/models/login_asset_acl.py:9 +#: acls/serializers/login_acl.py:15 acls/serializers/login_asset_acl.py:13 +msgid "Rule" +msgstr "" + +#: acls/models/login_acl.py:14 +msgid "Login acl" +msgstr "" + +#: acls/models/login_acl.py:27 tickets/const.py:11 +msgid "Login confirm" +msgstr "" + +#: acls/models/login_asset_acl.py:12 +msgid "Login asset acl" +msgstr "" + +#: acls/models/login_asset_acl.py:22 tickets/const.py:13 +msgid "Login asset confirm" +msgstr "" + +#: acls/notifications.py:12 +msgid "User login reminder" +msgstr "" + +#: acls/notifications.py:42 +msgid "Asset login reminder" +msgstr "" + +#: acls/serializers/base.py:11 acls/serializers/login_acl.py:11 +msgid "With * indicating a match all. " +msgstr "" + +#: acls/serializers/base.py:26 +msgid "" +"With * indicating a match all. Such as: 192.168.10.1, 192.168.1.0/24, " +"10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 (Domain name " +"support)" +msgstr "" + +#: acls/serializers/base.py:41 assets/serializers/asset/host.py:19 +msgid "IP/Host" +msgstr "" + +#: acls/serializers/base.py:91 +msgid "Recipients" +msgstr "" + +#: acls/serializers/base.py:103 tickets/serializers/ticket/ticket.py:77 +msgid "The organization `{}` does not exist" +msgstr "" + +#: acls/serializers/base.py:109 +msgid "None of the reviewers belong to Organization `{}`" +msgstr "" + +#: acls/serializers/rules/rules.py:20 +#: xpack/plugins/cloud/serializers/task.py:145 +msgid "IP address invalid: `{}`" +msgstr "" + +#: acls/serializers/rules/rules.py:25 +msgid "" +"With * indicating a match all. Such as: 192.168.10.1, 192.168.1.0/24, " +"10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 " +msgstr "" + +#: acls/serializers/rules/rules.py:33 +#: authentication/templates/authentication/_msg_oauth_bind.html:12 +#: authentication/templates/authentication/_msg_rest_password_success.html:8 +#: authentication/templates/authentication/_msg_rest_public_key_success.html:8 +msgid "IP" +msgstr "" + +#: acls/serializers/rules/rules.py:35 +msgid "Time Period" +msgstr "" + +#: acls/templates/acls/asset_login_reminder.html:10 +msgid "" +"The user has just logged in to the asset. Please ensure that this is an " +"authorized operation. If you suspect that this is an unauthorized access, " +"please take appropriate measures immediately." +msgstr "" + +#: acls/templates/acls/asset_login_reminder.html:12 +#: acls/templates/acls/user_login_reminder.html:13 +msgid "Thank you" +msgstr "" + +#: acls/templates/acls/user_login_reminder.html:7 audits/models.py:194 +#: audits/models.py:263 +#: authentication/templates/authentication/_msg_different_city.html:11 +#: tickets/models/ticket/login_confirm.py:11 +msgid "Login city" +msgstr "" + +#: acls/templates/acls/user_login_reminder.html:8 audits/models.py:197 +#: audits/models.py:264 audits/serializers.py:68 +msgid "User agent" +msgstr "" + +#: acls/templates/acls/user_login_reminder.html:11 +msgid "" +"The user has just successfully logged into the system. Please ensure that " +"this is an authorized operation. If you suspect that this is an unauthorized " +"access, please take appropriate measures immediately." +msgstr "" + +#: assets/api/asset/asset.py:180 +msgid "Cannot create asset directly, you should create a host or other" +msgstr "" + +#: assets/api/domain.py:67 +msgid "Number required" +msgstr "" + +#: assets/api/node.py:58 +msgid "You can't update the root node name" +msgstr "" + +#: assets/api/node.py:65 +msgid "You can't delete the root node ({})" +msgstr "" + +#: assets/api/node.py:68 +msgid "Deletion failed and the node contains assets" +msgstr "" + +#: assets/api/tree.py:49 assets/serializers/node.py:42 +msgid "The same level node name cannot be the same" +msgstr "" + +#: assets/apps.py:9 +msgid "App Assets" +msgstr "" + +#: assets/automations/base/manager.py:191 +msgid "{} disabled" +msgstr "" + +#: assets/automations/base/manager.py:254 +msgid " - Platform {} ansible disabled" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:33 +#: authentication/models/connection_token.py:131 +msgid "No account" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:36 +msgid "Asset, {}, using account {}" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:55 +#, python-brace-format +msgid "Unable to connect to port {port} on {address}" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:58 +#: authentication/backends/oauth2/views.py:60 authentication/middleware.py:93 +#: xpack/plugins/cloud/providers/fc.py:47 +msgid "Authentication failed" +msgstr "" + +#: assets/automations/ping_gateway/manager.py:60 +#: assets/automations/ping_gateway/manager.py:86 terminal/const.py:102 +msgid "Connect failed" +msgstr "" + +#: assets/const/automation.py:6 audits/const.py:6 audits/const.py:44 +#: audits/signal_handlers/activity_log.py:62 common/utils/ip/geoip/utils.py:31 +#: common/utils/ip/geoip/utils.py:37 common/utils/ip/utils.py:104 +msgid "Unknown" +msgstr "" + +#: assets/const/automation.py:7 +msgid "Ok" +msgstr "" + +#: assets/const/automation.py:12 +msgid "Ping" +msgstr "" + +#: assets/const/automation.py:13 +msgid "Ping gateway" +msgstr "" + +#: assets/const/automation.py:14 +msgid "Gather facts" +msgstr "" + +#: assets/const/base.py:32 audits/const.py:55 +#: terminal/serializers/applet_host.py:32 +msgid "Disabled" +msgstr "" + +#: assets/const/base.py:33 settings/serializers/basic.py:8 +#: users/serializers/preference/koko.py:19 +#: users/serializers/preference/lina.py:39 +#: users/serializers/preference/luna.py:77 +msgid "Basic" +msgstr "" + +#: assets/const/base.py:34 assets/const/protocol.py:268 +#: assets/models/asset/web.py:13 +msgid "Script" +msgstr "" + +#: assets/const/category.py:10 assets/models/asset/host.py:8 +#: settings/serializers/auth/radius.py:16 settings/serializers/auth/sms.py:71 +#: settings/serializers/feature.py:49 settings/serializers/msg.py:31 +#: terminal/models/component/endpoint.py:13 terminal/serializers/applet.py:17 +#: xpack/plugins/cloud/serializers/account_attrs.py:72 +msgid "Host" +msgstr "" + +#: assets/const/category.py:11 assets/models/asset/device.py:8 +msgid "Device" +msgstr "" + +#: assets/const/category.py:13 +msgid "Cloud service" +msgstr "" + +#: assets/const/category.py:14 assets/models/asset/gpt.py:11 +#: assets/models/asset/web.py:16 audits/const.py:42 +#: terminal/models/applet/applet.py:27 users/const.py:64 +msgid "Web" +msgstr "" + +#: assets/const/category.py:16 common/sdk/sms/endpoint.py:20 +msgid "Custom type" +msgstr "" + +#: assets/const/cloud.py:7 +msgid "Public cloud" +msgstr "" + +#: assets/const/cloud.py:8 +msgid "Private cloud" +msgstr "" + +#: assets/const/cloud.py:9 +msgid "Kubernetes" +msgstr "" + +#: assets/const/device.py:7 terminal/models/applet/applet.py:26 +#: tickets/const.py:9 +msgid "General" +msgstr "" + +#: assets/const/device.py:8 +msgid "Switch" +msgstr "" + +#: assets/const/device.py:9 +msgid "Router" +msgstr "" + +#: assets/const/device.py:10 +msgid "Firewall" +msgstr "" + +#: assets/const/gpt.py:7 +msgid "ChatGPT" +msgstr "" + +#: assets/const/host.py:12 rbac/tree.py:28 +msgid "Other" +msgstr "" + +#: assets/const/protocol.py:45 +msgid "Old SSH version" +msgstr "" + +#: assets/const/protocol.py:46 +msgid "Old SSH version like openssh 5.x or 6.x" +msgstr "" + +#: assets/const/protocol.py:57 +msgid "SFTP root" +msgstr "" + +#: assets/const/protocol.py:59 +#, python-brace-format +msgid "" +"SFTP root directory, Support variable:
- ${ACCOUNT} The connected " +"account username
- ${HOME} The home directory of the connected account " +"
- ${USER} The username of the user" +msgstr "" + +#: assets/const/protocol.py:74 +msgid "Console" +msgstr "" + +#: assets/const/protocol.py:75 +msgid "Connect to console session" +msgstr "" + +#: assets/const/protocol.py:79 +msgid "Any" +msgstr "" + +#: assets/const/protocol.py:81 settings/serializers/security.py:232 +msgid "Security" +msgstr "" + +#: assets/const/protocol.py:82 +msgid "Security layer to use for the connection" +msgstr "" + +#: assets/const/protocol.py:88 +msgid "AD domain" +msgstr "" + +#: assets/const/protocol.py:103 +msgid "Username prompt" +msgstr "" + +#: assets/const/protocol.py:104 +msgid "We will send username when we see this prompt" +msgstr "" + +#: assets/const/protocol.py:109 +msgid "Password prompt" +msgstr "" + +#: assets/const/protocol.py:110 +msgid "We will send password when we see this prompt" +msgstr "" + +#: assets/const/protocol.py:115 +msgid "Success prompt" +msgstr "" + +#: assets/const/protocol.py:116 +msgid "We will consider login success when we see this prompt" +msgstr "" + +#: assets/const/protocol.py:127 assets/models/asset/database.py:10 +#: settings/serializers/msg.py:47 +msgid "Use SSL" +msgstr "" + +#: assets/const/protocol.py:162 +msgid "SYSDBA" +msgstr "" + +#: assets/const/protocol.py:163 +msgid "Connect as SYSDBA" +msgstr "" + +#: assets/const/protocol.py:178 +msgid "" +"SQL Server version, Different versions have different connection drivers" +msgstr "" + +#: assets/const/protocol.py:202 +msgid "Auth source" +msgstr "" + +#: assets/const/protocol.py:203 +msgid "The database to authenticate against" +msgstr "" + +#: assets/const/protocol.py:215 +msgid "Auth username" +msgstr "" + +#: assets/const/protocol.py:238 +msgid "Safe mode" +msgstr "" + +#: assets/const/protocol.py:240 +msgid "" +"When safe mode is enabled, some operations will be disabled, such as: New " +"tab, right click, visit other website, etc." +msgstr "" + +#: assets/const/protocol.py:245 assets/models/asset/web.py:9 +#: assets/serializers/asset/info/spec.py:16 +msgid "Autofill" +msgstr "" + +#: assets/const/protocol.py:253 assets/models/asset/web.py:10 +msgid "Username selector" +msgstr "" + +#: assets/const/protocol.py:258 assets/models/asset/web.py:11 +msgid "Password selector" +msgstr "" + +#: assets/const/protocol.py:263 assets/models/asset/web.py:12 +msgid "Submit selector" +msgstr "" + +#: assets/const/protocol.py:286 +msgid "API mode" +msgstr "" + +#: assets/const/types.py:251 +msgid "All types" +msgstr "" + +#: assets/const/web.py:7 +msgid "Website" +msgstr "" + +#: assets/exceptions.py:12 +msgid "This function is not supported temporarily" +msgstr "" + +#: assets/models/asset/cloud.py:11 +msgid "Cloud" +msgstr "" + +#: assets/models/asset/common.py:94 assets/models/platform.py:16 +#: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:72 +#: settings/serializers/msg.py:32 terminal/serializers/storage.py:133 +#: xpack/plugins/cloud/serializers/account_attrs.py:73 +msgid "Port" +msgstr "" + +#: assets/models/asset/common.py:160 assets/serializers/asset/common.py:150 +#: settings/serializers/terminal.py:10 +msgid "Address" +msgstr "" + +#: assets/models/asset/common.py:161 assets/models/platform.py:134 +#: authentication/backends/passkey/models.py:12 +#: authentication/serializers/connect_token_secret.py:118 +#: perms/serializers/user_permission.py:25 xpack/plugins/cloud/models.py:329 +msgid "Platform" +msgstr "" + +#: assets/models/asset/common.py:163 +#: authentication/serializers/connect_token_secret.py:136 +#: perms/serializers/user_permission.py:28 xpack/plugins/cloud/models.py:331 +msgid "Domain" +msgstr "" + +#: assets/models/asset/common.py:166 assets/serializers/asset/common.py:385 +#: assets/serializers/asset/host.py:11 +msgid "Gathered info" +msgstr "" + +#: assets/models/asset/common.py:167 assets/serializers/asset/custom.py:14 +msgid "Custom info" +msgstr "" + +#: assets/models/asset/common.py:352 +msgid "Can refresh asset hardware info" +msgstr "" + +#: assets/models/asset/common.py:353 +msgid "Can test asset connectivity" +msgstr "" + +#: assets/models/asset/common.py:354 +msgid "Can match asset" +msgstr "" + +#: assets/models/asset/common.py:355 +msgid "Can change asset nodes" +msgstr "" + +#: assets/models/asset/custom.py:8 +msgid "Custom asset" +msgstr "" + +#: assets/models/asset/database.py:11 +msgid "CA cert" +msgstr "" + +#: assets/models/asset/database.py:12 +msgid "Client cert" +msgstr "" + +#: assets/models/asset/database.py:13 +msgid "Client key" +msgstr "" + +#: assets/models/asset/database.py:14 +msgid "Allow invalid cert" +msgstr "" + +#: assets/models/asset/gpt.py:8 settings/serializers/feature.py:84 +msgid "Proxy" +msgstr "" + +#: assets/models/automations/base.py:18 assets/models/cmd_filter.py:32 +#: assets/models/node.py:553 perms/models/asset_permission.py:72 +#: tickets/models/ticket/apply_asset.py:14 xpack/plugins/cloud/models.py:330 +msgid "Node" +msgstr "" + +#: assets/models/automations/base.py:22 ops/models/job.py:236 +#: settings/serializers/auth/sms.py:103 +msgid "Parameters" +msgstr "" + +#: assets/models/automations/base.py:29 assets/models/automations/base.py:111 +msgid "Automation task" +msgstr "" + +#: assets/models/automations/base.py:104 +msgid "Asset automation task" +msgstr "" + +#: assets/models/automations/base.py:114 assets/models/cmd_filter.py:41 +#: audits/models.py:267 common/db/models.py:34 ops/models/base.py:54 +#: ops/models/job.py:240 users/models/user.py:1101 +msgid "Date created" +msgstr "" + +#: assets/models/automations/gather_facts.py:15 +msgid "Gather asset facts" +msgstr "" + +#: assets/models/automations/ping.py:15 +msgid "Ping asset" +msgstr "" + +#: assets/models/base.py:19 terminal/notifications.py:225 +msgid "Connectivity" +msgstr "" + +#: assets/models/base.py:21 authentication/models/temp_token.py:12 +msgid "Date verified" +msgstr "" + +#: assets/models/cmd_filter.py:28 perms/models/asset_permission.py:66 +#: users/models/group.py:25 users/models/user.py:880 +msgid "User group" +msgstr "" + +#: assets/models/cmd_filter.py:42 common/db/models.py:35 +#: users/models/user.py:936 +msgid "Date updated" +msgstr "" + +#: assets/models/cmd_filter.py:44 assets/models/cmd_filter.py:91 +#: common/db/models.py:32 users/models/user.py:917 +#: users/serializers/group.py:32 +msgid "Created by" +msgstr "" + +#: assets/models/cmd_filter.py:52 +msgid "Command filter" +msgstr "" + +#: assets/models/cmd_filter.py:66 +msgid "Deny" +msgstr "" + +#: assets/models/cmd_filter.py:67 +msgid "Allow" +msgstr "" + +#: assets/models/cmd_filter.py:68 +msgid "Reconfirm" +msgstr "" + +#: assets/models/cmd_filter.py:72 +msgid "Filter" +msgstr "" + +#: assets/models/cmd_filter.py:95 +msgid "Command filter rule" +msgstr "" + +#: assets/models/domain.py:22 +msgid "Zone" +msgstr "" + +#: assets/models/favorite_asset.py:17 +msgid "Favorite asset" +msgstr "" + +#: assets/models/gateway.py:34 assets/serializers/domain.py:19 +msgid "Gateway" +msgstr "" + +#: assets/models/label.py:15 rbac/const.py:6 users/models/user.py:1086 +msgid "System" +msgstr "" + +#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 +#: assets/serializers/cagegory.py:24 +#: authentication/models/connection_token.py:29 +#: authentication/serializers/connect_token_secret.py:125 +#: common/serializers/common.py:86 labels/models.py:12 settings/models.py:35 +#: users/models/preference.py:13 +msgid "Value" +msgstr "" + +#: assets/models/label.py:40 assets/serializers/cagegory.py:10 +#: assets/serializers/cagegory.py:17 assets/serializers/cagegory.py:23 +#: assets/serializers/platform.py:144 +#: authentication/serializers/connect_token_secret.py:124 +#: common/serializers/common.py:85 labels/models.py:17 labels/models.py:33 +#: labels/serializers.py:45 settings/serializers/msg.py:90 +msgid "Label" +msgstr "" + +#: assets/models/node.py:169 +msgid "New node" +msgstr "" + +#: assets/models/node.py:467 audits/backends/db.py:65 audits/backends/db.py:66 +msgid "empty" +msgstr "" + +#: assets/models/node.py:538 perms/models/perm_node.py:28 +msgid "Key" +msgstr "" + +#: assets/models/node.py:540 assets/serializers/node.py:20 +msgid "Full value" +msgstr "" + +#: assets/models/node.py:544 perms/models/perm_node.py:30 +msgid "Parent key" +msgstr "" + +#: assets/models/node.py:556 +msgid "Can match node" +msgstr "" + +#: assets/models/platform.py:17 +msgid "Primary" +msgstr "" + +#: assets/models/platform.py:18 +msgid "Required" +msgstr "" + +#: assets/models/platform.py:19 assets/serializers/platform.py:146 +#: xpack/plugins/cloud/providers/nutanix.py:30 +msgid "Default" +msgstr "" + +#: assets/models/platform.py:20 +msgid "Public" +msgstr "" + +#: assets/models/platform.py:21 assets/serializers/platform.py:74 +#: settings/serializers/settings.py:95 +#: users/templates/users/reset_password.html:29 +msgid "Setting" +msgstr "" + +#: assets/models/platform.py:38 audits/const.py:56 +#: authentication/backends/passkey/models.py:11 settings/models.py:38 +#: terminal/serializers/applet_host.py:33 +msgid "Enabled" +msgstr "" + +#: assets/models/platform.py:39 +msgid "Ansible config" +msgstr "" + +#: assets/models/platform.py:41 assets/serializers/platform.py:33 +msgid "Ping enabled" +msgstr "" + +#: assets/models/platform.py:42 assets/serializers/platform.py:34 +msgid "Ping method" +msgstr "" + +#: assets/models/platform.py:43 +msgid "Ping params" +msgstr "" + +#: assets/models/platform.py:45 assets/models/platform.py:69 +#: assets/serializers/platform.py:36 +msgid "Gather facts enabled" +msgstr "" + +#: assets/models/platform.py:47 assets/models/platform.py:71 +#: assets/serializers/platform.py:40 +msgid "Gather facts method" +msgstr "" + +#: assets/models/platform.py:49 assets/models/platform.py:73 +msgid "Gather facts params" +msgstr "" + +#: assets/models/platform.py:51 assets/serializers/platform.py:50 +msgid "Change secret enabled" +msgstr "" + +#: assets/models/platform.py:53 assets/serializers/platform.py:54 +msgid "Change secret method" +msgstr "" + +#: assets/models/platform.py:55 +msgid "Change secret params" +msgstr "" + +#: assets/models/platform.py:57 assets/serializers/platform.py:57 +msgid "Push account enabled" +msgstr "" + +#: assets/models/platform.py:59 assets/serializers/platform.py:61 +msgid "Push account method" +msgstr "" + +#: assets/models/platform.py:61 +msgid "Push account params" +msgstr "" + +#: assets/models/platform.py:63 assets/serializers/platform.py:43 +msgid "Verify account enabled" +msgstr "" + +#: assets/models/platform.py:65 assets/serializers/platform.py:47 +msgid "Verify account method" +msgstr "" + +#: assets/models/platform.py:67 +msgid "Verify account params" +msgstr "" + +#: assets/models/platform.py:75 +msgid "Remove account enabled" +msgstr "" + +#: assets/models/platform.py:77 +msgid "Remove account method" +msgstr "" + +#: assets/models/platform.py:79 +msgid "Remove account params" +msgstr "" + +#: assets/models/platform.py:97 tickets/models/ticket/general.py:298 +msgid "Meta" +msgstr "" + +#: assets/models/platform.py:98 labels/models.py:13 +msgid "Internal" +msgstr "" + +#: assets/models/platform.py:102 assets/serializers/platform.py:163 +msgid "Charset" +msgstr "" + +#: assets/models/platform.py:104 assets/serializers/platform.py:198 +msgid "Domain enabled" +msgstr "" + +#: assets/models/platform.py:106 assets/serializers/platform.py:191 +msgid "Su enabled" +msgstr "" + +#: assets/models/platform.py:107 assets/serializers/platform.py:169 +msgid "Su method" +msgstr "" + +#: assets/models/platform.py:108 assets/serializers/platform.py:172 +msgid "Custom fields" +msgstr "" + +#: assets/models/utils.py:18 +#, python-format +msgid "%(value)s is not an even number" +msgstr "" + +#: assets/notifications.py:12 +msgid "" +"Batch update platform in assets, skipping assets that do not meet platform " +"type" +msgstr "" + +#: assets/serializers/asset/common.py:127 assets/serializers/platform.py:166 +#: authentication/serializers/connect_token_secret.py:30 +#: authentication/serializers/connect_token_secret.py:75 +#: perms/models/asset_permission.py:76 perms/serializers/permission.py:46 +#: perms/serializers/user_permission.py:74 xpack/plugins/cloud/models.py:332 +#: xpack/plugins/cloud/serializers/task.py:33 +msgid "Protocols" +msgstr "" + +#: assets/serializers/asset/common.py:129 +#: assets/serializers/asset/common.py:151 +msgid "Node path" +msgstr "" + +#: assets/serializers/asset/common.py:148 +#: assets/serializers/asset/common.py:386 +msgid "Auto info" +msgstr "" + +#: assets/serializers/asset/common.py:245 +msgid "Platform not exist" +msgstr "" + +#: assets/serializers/asset/common.py:281 +msgid "port out of range (0-65535)" +msgstr "" + +#: assets/serializers/asset/common.py:288 +msgid "Protocol is required: {}" +msgstr "" + +#: assets/serializers/asset/common.py:316 +msgid "Invalid data" +msgstr "" + +#: assets/serializers/asset/database.py:13 +msgid "Default database" +msgstr "" + +#: assets/serializers/asset/gpt.py:20 +msgid "" +"If the server cannot directly connect to the API address, you need set up an " +"HTTP proxy. e.g. http(s)://host:port" +msgstr "" + +#: assets/serializers/asset/gpt.py:24 +msgid "HTTP proxy" +msgstr "" + +#: assets/serializers/asset/gpt.py:31 +msgid "Proxy must start with http:// or https://" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:6 +msgid "Vendor" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:7 +msgid "Model" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:8 +#: tickets/models/ticket/general.py:297 +msgid "Serial number" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:9 +msgid "CPU model" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:10 +msgid "CPU count" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:11 +msgid "CPU cores" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:12 +msgid "CPU vcpus" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:13 +msgid "Memory" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:14 +msgid "Disk total" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:16 +#: authentication/serializers/connect_token_secret.py:115 +msgid "OS" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:17 +msgid "OS version" +msgstr "" + +#: assets/serializers/asset/info/gathered.py:18 +msgid "OS arch" +msgstr "" + +#: assets/serializers/cagegory.py:13 +msgid "Constraints" +msgstr "" + +#: assets/serializers/cagegory.py:19 +msgid "Types" +msgstr "" + +#: assets/serializers/domain.py:21 orgs/serializers.py:13 +#: perms/serializers/permission.py:40 +msgid "Assets amount" +msgstr "" + +#: assets/serializers/gateway.py:23 common/validators.py:34 +msgid "This field must be unique." +msgstr "" + +#: assets/serializers/node.py:17 +msgid "value" +msgstr "" + +#: assets/serializers/node.py:31 +msgid "Can't contains: /" +msgstr "" + +#: assets/serializers/platform.py:33 +msgid "Enable asset detection" +msgstr "" + +#: assets/serializers/platform.py:37 +msgid "Enable asset information collection" +msgstr "" + +#: assets/serializers/platform.py:44 +msgid "Enable account verification" +msgstr "" + +#: assets/serializers/platform.py:51 +msgid "Enable account secret auto change" +msgstr "" + +#: assets/serializers/platform.py:58 +msgid "Enable account auto push" +msgstr "" + +#: assets/serializers/platform.py:64 +msgid "Gather accounts enabled" +msgstr "" + +#: assets/serializers/platform.py:65 +msgid "Enable account collection" +msgstr "" + +#: assets/serializers/platform.py:68 +msgid "Gather accounts method" +msgstr "" + +#: assets/serializers/platform.py:75 +msgid "Port from addr" +msgstr "" + +#: assets/serializers/platform.py:87 +msgid "" +"This protocol is primary, and it must be set when adding assets. " +"Additionally, there can only be one primary protocol." +msgstr "" + +#: assets/serializers/platform.py:92 +msgid "This protocol is required, and it must be set when adding assets." +msgstr "" + +#: assets/serializers/platform.py:95 +msgid "" +"This protocol is default, when adding assets, it will be displayed by " +"default." +msgstr "" + +#: assets/serializers/platform.py:98 +msgid "This protocol is public, asset will show this protocol to user" +msgstr "" + +#: assets/serializers/platform.py:147 +msgid "Help text" +msgstr "" + +#: assets/serializers/platform.py:148 +msgid "Choices" +msgstr "" + +#: assets/serializers/platform.py:167 +msgid "Automation" +msgstr "" + +#: assets/serializers/platform.py:193 +msgid "" +"Login with account when accessing assets, then automatically switch to " +"another, similar to logging in with a regular account and then switching to " +"root" +msgstr "" + +#: assets/serializers/platform.py:199 +msgid "Assets can be connected using a domain gateway" +msgstr "" + +#: assets/serializers/platform.py:201 +msgid "Default Domain" +msgstr "" + +#: assets/serializers/platform.py:222 +msgid "type is required" +msgstr "" + +#: assets/serializers/platform.py:237 +msgid "Protocols is required" +msgstr "" + +#: assets/signal_handlers/asset.py:26 assets/tasks/ping.py:35 +msgid "Test assets connectivity " +msgstr "" + +#: assets/signal_handlers/asset.py:36 +msgid "Gather asset hardware info" +msgstr "" + +#: assets/tasks/automation.py:24 +msgid "Asset execute automation" +msgstr "" + +#: assets/tasks/gather_facts.py:21 assets/tasks/gather_facts.py:27 +msgid "Gather assets facts" +msgstr "" + +#: assets/tasks/gather_facts.py:39 +msgid "Update assets hardware info: " +msgstr "" + +#: assets/tasks/gather_facts.py:47 +msgid "Update node asset hardware information: " +msgstr "" + +#: assets/tasks/nodes_amount.py:16 +msgid "Check the amount of assets under the node" +msgstr "" + +#: assets/tasks/nodes_amount.py:28 +msgid "" +"The task of self-checking is already running and cannot be started repeatedly" +msgstr "" + +#: assets/tasks/nodes_amount.py:33 +msgid "Periodic check the amount of assets under the node" +msgstr "" + +#: assets/tasks/ping.py:20 assets/tasks/ping.py:26 +msgid "Test assets connectivity" +msgstr "" + +#: assets/tasks/ping.py:42 +msgid "Test if the assets under the node are connectable " +msgstr "" + +#: assets/tasks/ping_gateway.py:19 assets/tasks/ping_gateway.py:25 +#: assets/tasks/ping_gateway.py:34 +msgid "Test gateways connectivity" +msgstr "" + +#: assets/tasks/utils.py:16 +msgid "Asset has been disabled, skipped: {}" +msgstr "" + +#: assets/tasks/utils.py:20 +msgid "Asset may not be support ansible, skipped: {}" +msgstr "" + +#: assets/tasks/utils.py:38 +msgid "For security, do not push user {}" +msgstr "" + +#: assets/tasks/utils.py:54 +msgid "No assets matched, stop task" +msgstr "" + +#: audits/apps.py:9 +msgid "App Audits" +msgstr "" + +#: audits/backends/db.py:16 +msgid "The text content is too long. Use Elasticsearch to store operation logs" +msgstr "" + +#: audits/backends/db.py:91 +msgid "Tips" +msgstr "" + +#: audits/const.py:12 +msgid "Mkdir" +msgstr "" + +#: audits/const.py:13 +msgid "Rmdir" +msgstr "" + +#: audits/const.py:14 audits/const.py:25 +#: authentication/templates/authentication/_access_key_modal.html:65 +#: rbac/tree.py:240 +msgid "Delete" +msgstr "" + +#: audits/const.py:15 +msgid "Upload" +msgstr "" + +#: audits/const.py:16 +msgid "Rename" +msgstr "" + +#: audits/const.py:17 +msgid "Symlink" +msgstr "" + +#: audits/const.py:18 audits/const.py:28 terminal/api/session/session.py:149 +msgid "Download" +msgstr "" + +#: audits/const.py:19 +msgid "Rename dir" +msgstr "" + +#: audits/const.py:23 rbac/tree.py:238 terminal/api/session/session.py:277 +#: terminal/templates/terminal/_msg_command_warning.html:18 +#: terminal/templates/terminal/_msg_session_sharing.html:10 +msgid "View" +msgstr "" + +#: audits/const.py:26 +#: authentication/templates/authentication/_access_key_modal.html:22 +#: rbac/tree.py:237 +msgid "Create" +msgstr "" + +#: audits/const.py:29 +msgid "Connect" +msgstr "" + +#: audits/const.py:30 authentication/templates/authentication/login.html:296 +#: authentication/templates/authentication/login.html:368 +#: templates/_header_bar.html:101 +msgid "Login" +msgstr "" + +#: audits/const.py:31 ops/const.py:9 +msgid "Change password" +msgstr "" + +#: audits/const.py:35 +msgid "Notifications" +msgstr "" + +#: audits/const.py:37 tickets/const.py:45 +msgid "Approve" +msgstr "" + +#: audits/const.py:38 +#: authentication/templates/authentication/_access_key_modal.html:155 +#: authentication/templates/authentication/_mfa_confirm_modal.html:53 +#: templates/_modal.html:22 tickets/const.py:43 +msgid "Close" +msgstr "" + +#: audits/const.py:43 settings/serializers/terminal.py:6 +#: terminal/models/applet/host.py:26 terminal/models/component/terminal.py:175 +#: terminal/models/virtualapp/provider.py:14 terminal/serializers/session.py:55 +#: terminal/serializers/session.py:69 +msgid "Terminal" +msgstr "" + +#: audits/const.py:48 audits/models.py:132 +msgid "Operate log" +msgstr "" + +#: audits/const.py:49 +msgid "Session log" +msgstr "" + +#: audits/const.py:50 +msgid "Login log" +msgstr "" + +#: audits/const.py:51 terminal/models/applet/host.py:144 +#: terminal/models/component/task.py:22 +msgid "Task" +msgstr "" + +#: audits/const.py:57 +msgid "-" +msgstr "" + +#: audits/handler.py:116 +msgid "Yes" +msgstr "" + +#: audits/handler.py:116 +msgid "No" +msgstr "" + +#: audits/models.py:47 +msgid "Job audit log" +msgstr "" + +#: audits/models.py:56 audits/models.py:100 audits/models.py:175 +#: terminal/models/session/session.py:39 terminal/models/session/sharing.py:113 +msgid "Remote addr" +msgstr "" + +#: audits/models.py:61 audits/serializers.py:38 +msgid "Operate" +msgstr "" + +#: audits/models.py:63 +msgid "Filename" +msgstr "" + +#: audits/models.py:66 common/serializers/common.py:98 +msgid "File" +msgstr "" + +#: audits/models.py:67 terminal/backends/command/models.py:21 +#: terminal/models/session/replay.py:9 terminal/models/session/sharing.py:20 +#: terminal/models/session/sharing.py:95 +#: terminal/templates/terminal/_msg_command_alert.html:10 +#: terminal/templates/terminal/_msg_command_warning.html:17 +#: tickets/models/ticket/command_confirm.py:15 +msgid "Session" +msgstr "" + +#: audits/models.py:70 +msgid "File transfer log" +msgstr "" + +#: audits/models.py:94 audits/serializers.py:86 +msgid "Resource Type" +msgstr "" + +#: audits/models.py:95 audits/models.py:98 audits/models.py:144 +#: audits/serializers.py:85 labels/serializers.py:46 +msgid "Resource" +msgstr "" + +#: audits/models.py:101 audits/models.py:147 audits/models.py:177 +#: terminal/serializers/command.py:75 +msgid "Datetime" +msgstr "" + +#: audits/models.py:140 +msgid "Activity type" +msgstr "" + +#: audits/models.py:150 +msgid "Detail" +msgstr "" + +#: audits/models.py:153 +msgid "Detail ID" +msgstr "" + +#: audits/models.py:157 +msgid "Activity log" +msgstr "" + +#: audits/models.py:173 +msgid "Change by" +msgstr "" + +#: audits/models.py:183 +msgid "Password change log" +msgstr "" + +#: audits/models.py:190 audits/models.py:265 +msgid "Login type" +msgstr "" + +#: audits/models.py:192 audits/models.py:261 +#: tickets/models/ticket/login_confirm.py:10 +msgid "Login IP" +msgstr "" + +#: audits/models.py:200 audits/serializers.py:52 +#: authentication/templates/authentication/_mfa_confirm_modal.html:14 +#: users/forms/profile.py:63 users/models/user.py:897 +#: users/serializers/profile.py:102 +msgid "MFA" +msgstr "" + +#: audits/models.py:210 +#: authentication/templates/authentication/_msg_different_city.html:10 +#: tickets/models/ticket/login_confirm.py:12 +msgid "Login Date" +msgstr "" + +#: audits/models.py:212 audits/models.py:266 +msgid "Auth backend" +msgstr "" + +#: audits/models.py:256 +msgid "User login log" +msgstr "" + +#: audits/models.py:262 +msgid "Session key" +msgstr "" + +#: audits/models.py:298 +msgid "User session" +msgstr "" + +#: audits/models.py:300 +msgid "Offline user session" +msgstr "" + +#: audits/serializers.py:33 ops/models/adhoc.py:25 ops/models/base.py:16 +#: ops/models/base.py:53 ops/models/celery.py:86 ops/models/job.py:151 +#: ops/models/job.py:239 ops/models/playbook.py:30 +#: terminal/models/session/sharing.py:25 +msgid "Creator" +msgstr "" + +#: audits/serializers.py:69 +msgid "Reason display" +msgstr "" + +#: audits/serializers.py:70 audits/serializers.py:184 +msgid "Auth backend display" +msgstr "" + +#: audits/serializers.py:134 +#, python-format +msgid "%s %s this resource" +msgstr "" + +#: audits/serializers.py:172 authentication/models/connection_token.py:47 +#: authentication/models/temp_token.py:13 perms/models/asset_permission.py:80 +#: tickets/models/ticket/apply_application.py:31 +#: tickets/models/ticket/apply_asset.py:20 users/models/user.py:915 +msgid "Date expired" +msgstr "" + +#: audits/signal_handlers/activity_log.py:26 +#, python-format +msgid "User %s use account %s login asset %s" +msgstr "" + +#: audits/signal_handlers/activity_log.py:34 +#, python-format +msgid "User %s login system %s" +msgstr "" + +#: audits/signal_handlers/activity_log.py:64 +#, python-format +msgid "User %s perform a task for this resource: %s" +msgstr "" + +#: audits/signal_handlers/login_log.py:33 +msgid "SSH Key" +msgstr "" + +#: audits/signal_handlers/login_log.py:35 settings/serializers/auth/sso.py:13 +msgid "SSO" +msgstr "" + +#: audits/signal_handlers/login_log.py:36 +msgid "Auth Token" +msgstr "" + +#: audits/signal_handlers/login_log.py:37 authentication/notifications.py:73 +#: authentication/views/login.py:77 notifications/backends/__init__.py:11 +#: settings/serializers/auth/wecom.py:10 settings/serializers/auth/wecom.py:15 +#: users/models/user.py:758 users/models/user.py:930 +msgid "WeCom" +msgstr "" + +#: audits/signal_handlers/login_log.py:38 authentication/views/feishu.py:105 +#: authentication/views/login.py:89 notifications/backends/__init__.py:14 +#: settings/serializers/auth/feishu.py:10 users/models/user.py:760 +#: users/models/user.py:932 +msgid "FeiShu" +msgstr "" + +#: audits/signal_handlers/login_log.py:40 authentication/views/login.py:101 +#: authentication/views/slack.py:87 notifications/backends/__init__.py:16 +#: settings/serializers/auth/slack.py:10 settings/serializers/auth/slack.py:12 +#: users/models/user.py:762 users/models/user.py:934 +msgid "Slack" +msgstr "" + +#: audits/signal_handlers/login_log.py:41 authentication/views/dingtalk.py:161 +#: authentication/views/login.py:83 notifications/backends/__init__.py:12 +#: settings/serializers/auth/dingtalk.py:10 users/models/user.py:759 +#: users/models/user.py:931 +msgid "DingTalk" +msgstr "" + +#: audits/signal_handlers/login_log.py:42 +#: authentication/models/temp_token.py:16 +msgid "Temporary token" +msgstr "" + +#: audits/signal_handlers/login_log.py:43 authentication/views/login.py:107 +#: settings/serializers/auth/passkey.py:8 +#: settings/serializers/auth/passkey.py:11 +msgid "Passkey" +msgstr "" + +#: audits/tasks.py:117 +msgid "Clean audits session task log" +msgstr "" + +#: audits/tasks.py:130 +msgid "Upload FTP file to external storage" +msgstr "" + +#: authentication/api/access_key.py:39 +msgid "Access keys can be created at most 10" +msgstr "" + +#: authentication/api/common.py:34 settings/serializers/auth/sms.py:117 +#, python-format +msgid "The value in the parameter must contain %s" +msgstr "" + +#: authentication/api/confirm.py:50 +msgid "This action require verify your MFA" +msgstr "" + +#: authentication/api/connection_token.py:265 +msgid "Reusable connection token is not allowed, global setting not enabled" +msgstr "" + +#: authentication/api/connection_token.py:379 +msgid "Anonymous account is not supported for this asset" +msgstr "" + +#: authentication/api/connection_token.py:399 +msgid "Account not found" +msgstr "" + +#: authentication/api/connection_token.py:402 +msgid "Permission expired" +msgstr "" + +#: authentication/api/connection_token.py:435 +msgid "ACL action is reject: {}({})" +msgstr "" + +#: authentication/api/connection_token.py:439 +msgid "ACL action is review" +msgstr "" + +#: authentication/api/mfa.py:62 +msgid "Current user not support mfa type: {}" +msgstr "" + +#: authentication/api/password.py:33 terminal/api/session/session.py:325 +#: users/views/profile/reset.py:63 +msgid "User does not exist: {}" +msgstr "" + +#: authentication/api/password.py:33 users/views/profile/reset.py:166 +msgid "No user matched" +msgstr "" + +#: authentication/api/password.py:37 +msgid "" +"The user is from {}, please go to the corresponding system to change the " +"password" +msgstr "" + +#: authentication/api/password.py:65 +#: authentication/templates/authentication/login.html:360 +#: users/templates/users/forgot_password.html:41 +#: users/templates/users/forgot_password.html:42 +#: users/templates/users/forgot_password_previewing.html:13 +#: users/templates/users/forgot_password_previewing.html:14 +msgid "Forgot password" +msgstr "" + +#: authentication/apps.py:7 +msgid "App Authentication" +msgstr "" + +#: authentication/backends/custom.py:59 +#: authentication/backends/oauth2/backends.py:173 +msgid "User invalid, disabled or expired" +msgstr "" + +#: authentication/backends/drf.py:52 +msgid "Invalid token header. No credentials provided." +msgstr "" + +#: authentication/backends/drf.py:55 +msgid "Invalid token header. Sign string should not contain spaces." +msgstr "" + +#: authentication/backends/drf.py:61 +msgid "" +"Invalid token header. Sign string should not contain invalid characters." +msgstr "" + +#: authentication/backends/drf.py:74 +msgid "Invalid token or cache refreshed." +msgstr "" + +#: authentication/backends/passkey/api.py:37 +msgid "Only register passkey for local user" +msgstr "" + +#: authentication/backends/passkey/api.py:65 +msgid "Auth failed" +msgstr "" + +#: authentication/backends/passkey/fido.py:148 +msgid "This key is not registered" +msgstr "" + +#: authentication/backends/passkey/models.py:13 +msgid "Added on" +msgstr "" + +#: authentication/backends/passkey/models.py:14 +#: authentication/models/access_key.py:26 +#: authentication/models/private_token.py:8 +msgid "Date last used" +msgstr "" + +#: authentication/backends/passkey/models.py:15 +msgid "Credential ID" +msgstr "" + +#: authentication/confirm/password.py:16 +msgid "Authentication failed password incorrect" +msgstr "" + +#: authentication/confirm/relogin.py:10 +msgid "Login time has exceeded {} minutes, please login again" +msgstr "" + +#: authentication/errors/const.py:18 +msgid "Username/password check failed" +msgstr "" + +#: authentication/errors/const.py:19 +msgid "Password decrypt failed" +msgstr "" + +#: authentication/errors/const.py:20 +msgid "MFA failed" +msgstr "" + +#: authentication/errors/const.py:21 +msgid "MFA unset" +msgstr "" + +#: authentication/errors/const.py:22 +msgid "Username does not exist" +msgstr "" + +#: authentication/errors/const.py:23 +msgid "Password expired" +msgstr "" + +#: authentication/errors/const.py:24 +msgid "Disabled or expired" +msgstr "" + +#: authentication/errors/const.py:25 +msgid "This account is inactive." +msgstr "" + +#: authentication/errors/const.py:26 +msgid "This account is expired" +msgstr "" + +#: authentication/errors/const.py:27 +msgid "Auth backend not match" +msgstr "" + +#: authentication/errors/const.py:28 +msgid "ACL is not allowed" +msgstr "" + +#: authentication/errors/const.py:29 +msgid "Only local users are allowed" +msgstr "" + +#: authentication/errors/const.py:39 +msgid "No session found, check your cookie" +msgstr "" + +#: authentication/errors/const.py:41 +#, python-brace-format +msgid "" +"The username or password you entered is incorrect, please enter it again. " +"You can also try {times_try} times (The account will be temporarily locked " +"for {block_time} minutes)" +msgstr "" + +#: authentication/errors/const.py:47 authentication/errors/const.py:55 +msgid "" +"The account has been locked (please contact admin to unlock it or try again " +"after {} minutes)" +msgstr "" + +#: authentication/errors/const.py:51 +msgid "" +"The address has been locked (please contact admin to unlock it or try again " +"after {} minutes)" +msgstr "" + +#: authentication/errors/const.py:59 +#, python-brace-format +msgid "" +"{error}, You can also try {times_try} times (The account will be temporarily " +"locked for {block_time} minutes)" +msgstr "" + +#: authentication/errors/const.py:63 +msgid "MFA required" +msgstr "" + +#: authentication/errors/const.py:64 +msgid "MFA not set, please set it first" +msgstr "" + +#: authentication/errors/const.py:65 +msgid "Login confirm required" +msgstr "" + +#: authentication/errors/const.py:66 +msgid "Wait login confirm ticket for accept" +msgstr "" + +#: authentication/errors/const.py:67 +msgid "Login confirm ticket was {}" +msgstr "" + +#: authentication/errors/failed.py:149 +msgid "Current IP and Time period is not allowed" +msgstr "" + +#: authentication/errors/failed.py:154 +msgid "Please enter MFA code" +msgstr "" + +#: authentication/errors/failed.py:159 +msgid "Please enter SMS code" +msgstr "" + +#: authentication/errors/failed.py:164 users/exceptions.py:15 +msgid "Phone not set" +msgstr "" + +#: authentication/errors/mfa.py:8 +msgid "SSO auth closed" +msgstr "" + +#: authentication/errors/mfa.py:18 authentication/views/wecom.py:59 +msgid "WeCom is already bound" +msgstr "" + +#: authentication/errors/mfa.py:23 authentication/views/wecom.py:159 +#: authentication/views/wecom.py:201 +msgid "WeCom is not bound" +msgstr "" + +#: authentication/errors/mfa.py:28 authentication/views/dingtalk.py:213 +#: authentication/views/dingtalk.py:255 +msgid "DingTalk is not bound" +msgstr "" + +#: authentication/errors/mfa.py:33 authentication/views/feishu.py:138 +msgid "FeiShu is not bound" +msgstr "" + +#: authentication/errors/mfa.py:38 authentication/views/lark.py:48 +msgid "Lark is not bound" +msgstr "" + +#: authentication/errors/mfa.py:43 authentication/views/slack.py:127 +msgid "Slack is not bound" +msgstr "" + +#: authentication/errors/mfa.py:48 +msgid "Your password is invalid" +msgstr "" + +#: authentication/errors/mfa.py:53 +#, python-format +msgid "Please wait for %s seconds before retry" +msgstr "" + +#: authentication/errors/redirect.py:85 authentication/mixins.py:323 +msgid "Your password is too simple, please change it for security" +msgstr "" + +#: authentication/errors/redirect.py:93 authentication/mixins.py:330 +msgid "You should to change your password before login" +msgstr "" + +#: authentication/errors/redirect.py:101 authentication/mixins.py:337 +msgid "Your password has expired, please reset before logging in" +msgstr "" + +#: authentication/forms.py:39 +msgid "Auto login" +msgstr "" + +#: authentication/forms.py:52 +msgid "MFA Code" +msgstr "" + +#: authentication/forms.py:53 +msgid "MFA type" +msgstr "" + +#: authentication/forms.py:61 +#: authentication/templates/authentication/_captcha_field.html:15 +msgid "Captcha" +msgstr "" + +#: authentication/forms.py:66 users/forms/profile.py:27 +msgid "MFA code" +msgstr "" + +#: authentication/forms.py:68 +msgid "Dynamic code" +msgstr "" + +#: authentication/mfa/base.py:7 +msgid "Please input security code" +msgstr "" + +#: authentication/mfa/custom.py:20 +msgid "MFA Custom code invalid" +msgstr "" + +#: authentication/mfa/custom.py:26 +msgid "MFA custom verification code" +msgstr "" + +#: authentication/mfa/custom.py:56 +msgid "MFA custom global enabled, cannot disable" +msgstr "" + +#: authentication/mfa/otp.py:7 +msgid "OTP code invalid, or server time error" +msgstr "" + +#: authentication/mfa/otp.py:12 +msgid "OTP" +msgstr "" + +#: authentication/mfa/otp.py:13 +msgid "OTP verification code" +msgstr "" + +#: authentication/mfa/otp.py:48 +msgid "Virtual OTP based MFA" +msgstr "" + +#: authentication/mfa/radius.py:7 +msgid "Radius verify code invalid" +msgstr "" + +#: authentication/mfa/radius.py:13 +msgid "Radius verification code" +msgstr "" + +#: authentication/mfa/radius.py:44 +msgid "Radius global enabled, cannot disable" +msgstr "" + +#: authentication/mfa/sms.py:7 +msgid "SMS verify code invalid" +msgstr "" + +#: authentication/mfa/sms.py:12 authentication/serializers/password_mfa.py:16 +#: authentication/serializers/password_mfa.py:24 +#: settings/serializers/auth/sms.py:17 settings/serializers/auth/sms.py:32 +#: users/forms/profile.py:103 users/forms/profile.py:108 +#: users/templates/users/forgot_password.html:157 +#: users/views/profile/reset.py:100 +msgid "SMS" +msgstr "" + +#: authentication/mfa/sms.py:13 +msgid "SMS verification code" +msgstr "" + +#: authentication/mfa/sms.py:57 +msgid "Set phone number to enable" +msgstr "" + +#: authentication/mfa/sms.py:61 +msgid "Clear phone number to disable" +msgstr "" + +#: authentication/middleware.py:94 settings/utils/ldap.py:679 +msgid "Authentication failed (before login check failed): {}" +msgstr "" + +#: authentication/mixins.py:82 +msgid "User is invalid" +msgstr "" + +#: authentication/mixins.py:97 +msgid "" +"The administrator has enabled 'Only allow login from user source'. \n" +" The current user source is {}. Please contact the administrator." +msgstr "" + +#: authentication/mixins.py:273 +msgid "The MFA type ({}) is not enabled" +msgstr "" + +#: authentication/mixins.py:313 +msgid "Please change your password" +msgstr "" + +#: authentication/models/access_key.py:22 +#: terminal/models/component/endpoint.py:110 +msgid "IP group" +msgstr "" + +#: authentication/models/connection_token.py:38 +#: terminal/serializers/storage.py:114 +msgid "Account name" +msgstr "" + +#: authentication/models/connection_token.py:39 +msgid "Input username" +msgstr "" + +#: authentication/models/connection_token.py:40 +#: authentication/serializers/connection_token.py:18 +msgid "Input secret" +msgstr "" + +#: authentication/models/connection_token.py:41 +#: authentication/serializers/connect_token_secret.py:114 +#: settings/serializers/msg.py:29 terminal/models/applet/applet.py:42 +#: terminal/models/virtualapp/virtualapp.py:24 +#: terminal/serializers/session.py:21 terminal/serializers/session.py:48 +#: terminal/serializers/storage.py:71 +msgid "Protocol" +msgstr "" + +#: authentication/models/connection_token.py:42 +msgid "Connect method" +msgstr "" + +#: authentication/models/connection_token.py:43 +msgid "Connect options" +msgstr "" + +#: authentication/models/connection_token.py:44 +msgid "User display" +msgstr "" + +#: authentication/models/connection_token.py:45 +msgid "Asset display" +msgstr "" + +#: authentication/models/connection_token.py:46 +msgid "Reusable" +msgstr "" + +#: authentication/models/connection_token.py:51 +#: perms/models/asset_permission.py:83 +msgid "From ticket" +msgstr "" + +#: authentication/models/connection_token.py:58 +msgid "Can expire connection token" +msgstr "" + +#: authentication/models/connection_token.py:59 +msgid "Can reuse connection token" +msgstr "" + +#: authentication/models/connection_token.py:61 +msgid "Connection token" +msgstr "" + +#: authentication/models/connection_token.py:118 +msgid "Connection token inactive" +msgstr "" + +#: authentication/models/connection_token.py:122 +msgid "Connection token expired at: {}" +msgstr "" + +#: authentication/models/connection_token.py:125 +msgid "No user or invalid user" +msgstr "" + +#: authentication/models/connection_token.py:128 +msgid "No asset or inactive asset" +msgstr "" + +#: authentication/models/connection_token.py:274 +msgid "Can view super connection token secret" +msgstr "" + +#: authentication/models/connection_token.py:276 +msgid "Super connection token" +msgstr "" + +#: authentication/models/private_token.py:11 +msgid "Private Token" +msgstr "" + +#: authentication/models/sso_token.py:15 +msgid "Expired" +msgstr "" + +#: authentication/models/sso_token.py:20 +msgid "SSO token" +msgstr "" + +#: authentication/models/temp_token.py:11 +msgid "Verified" +msgstr "" + +#: authentication/notifications.py:19 +msgid "Different city login reminder" +msgstr "" + +#: authentication/notifications.py:52 +msgid "binding reminder" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:116 +msgid "Is builtin" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:120 +msgid "Options" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:127 +#: ops/notifications.py:18 +msgid "Component" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:138 +msgid "Expired now" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:170 +#: terminal/models/virtualapp/virtualapp.py:25 +msgid "Image name" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:171 +#: terminal/models/virtualapp/virtualapp.py:27 +msgid "Image port" +msgstr "" + +#: authentication/serializers/connect_token_secret.py:172 +#: terminal/models/virtualapp/virtualapp.py:26 +msgid "Image protocol" +msgstr "" + +#: authentication/serializers/connection_token.py:16 +msgid "Expired time" +msgstr "" + +#: authentication/serializers/connection_token.py:20 +msgid "Ticket info" +msgstr "" + +#: authentication/serializers/connection_token.py:21 +#: perms/models/asset_permission.py:77 perms/serializers/permission.py:42 +#: perms/serializers/permission.py:64 +#: tickets/models/ticket/apply_application.py:28 +#: tickets/models/ticket/apply_asset.py:18 +msgid "Actions" +msgstr "" + +#: authentication/serializers/connection_token.py:42 +#: perms/serializers/permission.py:44 perms/serializers/permission.py:65 +#: users/serializers/user.py:101 users/serializers/user.py:184 +msgid "Is expired" +msgstr "" + +#: authentication/serializers/password_mfa.py:29 +#: users/templates/users/forgot_password.html:153 +msgid "The {} cannot be empty" +msgstr "" + +#: authentication/serializers/token.py:22 +msgid "Access IP" +msgstr "" + +#: authentication/serializers/token.py:92 perms/serializers/permission.py:43 +#: perms/serializers/permission.py:66 users/serializers/user.py:102 +#: users/serializers/user.py:181 +msgid "Is valid" +msgstr "" + +#: authentication/tasks.py:11 +msgid "Clean expired session" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:6 +msgid "API key list" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:18 +msgid "Using api key sign api header, every requests header difference" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:19 +msgid "docs" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:48 +msgid "Show" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:66 +#: users/const.py:42 users/models/user.py:654 users/serializers/profile.py:92 +#: users/templates/users/user_verify_mfa.html:36 +msgid "Disable" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:67 +#: users/const.py:43 users/models/user.py:655 users/serializers/profile.py:93 +#: users/templates/users/mfa_setting.html:26 +#: users/templates/users/mfa_setting.html:68 +msgid "Enable" +msgstr "" + +#: authentication/templates/authentication/_access_key_modal.html:147 +msgid "Delete success" +msgstr "" + +#: authentication/templates/authentication/_captcha_field.html:8 +msgid "Play CAPTCHA as audio file" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:5 +msgid "MFA confirm" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:17 +msgid "Need MFA for view auth" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:20 +#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:37 +#: templates/_modal.html:23 templates/flash_message_standalone.html:37 +#: users/templates/users/user_password_verify.html:20 +msgid "Confirm" +msgstr "" + +#: authentication/templates/authentication/_mfa_confirm_modal.html:25 +msgid "Code error" +msgstr "" + +#: authentication/templates/authentication/_msg_different_city.html:3 +#: authentication/templates/authentication/_msg_oauth_bind.html:3 +#: authentication/templates/authentication/_msg_reset_password.html:3 +#: 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:465 +#: 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:32 +#: users/templates/users/_msg_account_expire_reminder.html:4 +#: users/templates/users/_msg_password_expire_reminder.html:4 +#: users/templates/users/_msg_reset_mfa.html:4 +#: users/templates/users/_msg_reset_ssh_key.html:4 +msgid "Hello" +msgstr "" + +#: authentication/templates/authentication/_msg_different_city.html:6 +msgid "Your account has remote login behavior, please pay attention" +msgstr "" + +#: authentication/templates/authentication/_msg_different_city.html:16 +msgid "" +"If you suspect that the login behavior is abnormal, please modify the " +"account password in time." +msgstr "" + +#: authentication/templates/authentication/_msg_oauth_bind.html:6 +msgid "Your account has just been bound to" +msgstr "" + +#: authentication/templates/authentication/_msg_oauth_bind.html:17 +msgid "If the operation is not your own, unbind and change the password." +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:6 +msgid "" +"Please click the link below to reset your password, if not your request, " +"concern your account security" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:10 +msgid "Click here reset password" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:16 +#: users/templates/users/_msg_user_created.html:22 +msgid "This link is valid for 1 hour. After it expires" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password.html:17 +#: users/templates/users/_msg_user_created.html:23 +msgid "request new one" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password_code.html:12 +#: terminal/models/session/sharing.py:27 terminal/models/session/sharing.py:97 +#: terminal/templates/terminal/_msg_session_sharing.html:12 +#: users/forms/profile.py:106 users/templates/users/forgot_password.html:98 +msgid "Verify code" +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password_code.html:15 +msgid "" +"Copy the verification code to the Reset Password page to reset the password." +msgstr "" + +#: authentication/templates/authentication/_msg_reset_password_code.html:18 +msgid "The validity period of the verification code is one minute" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:5 +msgid "Your password has just been successfully updated" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:9 +#: authentication/templates/authentication/_msg_rest_public_key_success.html:9 +msgid "Browser" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:13 +msgid "" +"If the password update was not initiated by you, your account may have " +"security issues" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_password_success.html:14 +#: authentication/templates/authentication/_msg_rest_public_key_success.html:14 +msgid "If you have any questions, you can contact the administrator" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_public_key_success.html:5 +msgid "Your public key has just been successfully updated" +msgstr "" + +#: authentication/templates/authentication/_msg_rest_public_key_success.html:13 +msgid "" +"If the public key update was not initiated by you, your account may have " +"security issues" +msgstr "" + +#: authentication/templates/authentication/auth_fail_flash_message_standalone.html:28 +#: templates/flash_message_standalone.html:28 tickets/const.py:18 +msgid "Cancel" +msgstr "" + +#: authentication/templates/authentication/login.html:276 +msgid "" +"Configuration file has problems and cannot be logged in. Please contact the " +"administrator or view latest docs" +msgstr "" + +#: authentication/templates/authentication/login.html:277 +msgid "If you are administrator, you can update the config resolve it, set" +msgstr "" + +#: authentication/templates/authentication/login.html:375 +msgid "More login options" +msgstr "" + +#: authentication/templates/authentication/login_mfa.html:6 +msgid "MFA Auth" +msgstr "" + +#: authentication/templates/authentication/login_mfa.html:19 +#: users/templates/users/user_otp_check_password.html:12 +#: users/templates/users/user_otp_enable_bind.html:24 +#: users/templates/users/user_otp_enable_install_app.html:31 +#: users/templates/users/user_verify_mfa.html:30 +msgid "Next" +msgstr "" + +#: authentication/templates/authentication/login_mfa.html:22 +msgid "Can't provide security? Please contact the administrator!" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:41 +msgid "Refresh" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:46 +msgid "Copy link" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:51 +msgid "Return" +msgstr "" + +#: authentication/templates/authentication/login_wait_confirm.html:117 +msgid "Copy success" +msgstr "" + +#: authentication/templates/authentication/passkey.html:162 +msgid "" +"This page is not served over HTTPS. Please use HTTPS to ensure security of " +"your credentials." +msgstr "" + +#: authentication/templates/authentication/passkey.html:173 +msgid "Do you want to retry ?" +msgstr "" + +#: authentication/utils.py:24 common/utils/ip/geoip/utils.py:24 +#: xpack/plugins/cloud/const.py:32 +msgid "LAN" +msgstr "" + +#: authentication/views/base.py:73 +#: perms/templates/perms/_msg_permed_items_expire.html:21 +msgid "If you have any question, please contact the administrator" +msgstr "" + +#: authentication/views/base.py:146 +#, python-format +msgid "%s query user failed" +msgstr "" + +#: authentication/views/base.py:155 +#, python-format +msgid "The %s is already bound to another user" +msgstr "" + +#: authentication/views/base.py:162 +#, python-format +msgid "Binding %s successfully" +msgstr "" + +#: authentication/views/dingtalk.py:42 +msgid "DingTalk Error, Please contact your system administrator" +msgstr "" + +#: authentication/views/dingtalk.py:45 authentication/views/dingtalk.py:212 +msgid "DingTalk Error" +msgstr "" + +#: authentication/views/dingtalk.py:57 authentication/views/feishu.py:68 +#: authentication/views/slack.py:47 authentication/views/wecom.py:55 +msgid "" +"The system configuration is incorrect. Please contact your administrator" +msgstr "" + +#: authentication/views/dingtalk.py:61 +msgid "DingTalk is already bound" +msgstr "" + +#: authentication/views/dingtalk.py:130 +msgid "Invalid user_id" +msgstr "" + +#: authentication/views/dingtalk.py:146 +msgid "DingTalk query user failed" +msgstr "" + +#: authentication/views/dingtalk.py:155 +msgid "The DingTalk is already bound to another user" +msgstr "" + +#: authentication/views/dingtalk.py:162 +msgid "Binding DingTalk successfully" +msgstr "" + +#: authentication/views/dingtalk.py:214 authentication/views/dingtalk.py:249 +msgid "Failed to get user from DingTalk" +msgstr "" + +#: authentication/views/dingtalk.py:256 +msgid "Please login with a password and then bind the DingTalk" +msgstr "" + +#: authentication/views/feishu.py:43 authentication/views/feishu.py:137 +msgid "FeiShu Error" +msgstr "" + +#: authentication/views/feishu.py:44 +msgid "FeiShu is already bound" +msgstr "" + +#: authentication/views/feishu.py:139 +msgid "Failed to get user from FeiShu" +msgstr "" + +#: authentication/views/lark.py:19 authentication/views/lark.py:47 +msgid "Lark Error" +msgstr "" + +#: authentication/views/lark.py:20 +msgid "Lark is already bound" +msgstr "" + +#: authentication/views/lark.py:49 +msgid "Failed to get user from Lark" +msgstr "" + +#: authentication/views/login.py:230 +msgid "Redirecting" +msgstr "" + +#: authentication/views/login.py:231 +msgid "Redirecting to {} authentication" +msgstr "" + +#: authentication/views/login.py:254 +msgid "Login timeout, please try again." +msgstr "" + +#: authentication/views/login.py:297 +msgid "User email already exists ({})" +msgstr "" + +#: authentication/views/login.py:375 +msgid "" +"Wait for {} confirm, You also can copy link to her/him
\n" +" Don't close this page" +msgstr "" + +#: authentication/views/login.py:380 +msgid "No ticket found" +msgstr "" + +#: authentication/views/login.py:416 +msgid "Logout success" +msgstr "" + +#: authentication/views/login.py:417 +msgid "Logout success, return login page" +msgstr "" + +#: authentication/views/slack.py:35 authentication/views/slack.py:126 +msgid "Slack Error" +msgstr "" + +#: authentication/views/slack.py:63 +msgid "Slack is already bound" +msgstr "" + +#: authentication/views/slack.py:128 +msgid "Failed to get user from Slack" +msgstr "" + +#: authentication/views/wecom.py:40 +msgid "WeCom Error, Please contact your system administrator" +msgstr "" + +#: authentication/views/wecom.py:43 authentication/views/wecom.py:158 +msgid "WeCom Error" +msgstr "" + +#: authentication/views/wecom.py:118 +msgid "Wecom" +msgstr "" + +#: authentication/views/wecom.py:160 authentication/views/wecom.py:195 +msgid "Failed to get user from WeCom" +msgstr "" + +#: authentication/views/wecom.py:202 +msgid "Please login with a password and then bind the WeCom" +msgstr "" + +#: common/api/action.py:51 +msgid "Request file format may be wrong" +msgstr "" + +#: common/const/choices.py:10 +msgid "Manual trigger" +msgstr "" + +#: common/const/choices.py:11 +msgid "Timing trigger" +msgstr "" + +#: common/const/choices.py:15 +msgid "Ready" +msgstr "" + +#: common/const/choices.py:17 ops/const.py:73 +msgid "Running" +msgstr "" + +#: common/const/choices.py:21 +msgid "Canceled" +msgstr "" + +#: common/const/common.py:5 +#, python-format +msgid "%(name)s was created successfully" +msgstr "" + +#: common/const/common.py:6 +#, python-format +msgid "%(name)s was updated successfully" +msgstr "" + +#: common/db/encoder.py:11 +msgid "gettext_lazy" +msgstr "" + +#: common/db/fields.py:106 +msgid "Marshal dict data to char field" +msgstr "" + +#: common/db/fields.py:110 +msgid "Marshal dict data to text field" +msgstr "" + +#: common/db/fields.py:122 +msgid "Marshal list data to char field" +msgstr "" + +#: common/db/fields.py:126 +msgid "Marshal list data to text field" +msgstr "" + +#: common/db/fields.py:130 +msgid "Marshal data to char field" +msgstr "" + +#: common/db/fields.py:134 +msgid "Marshal data to text field" +msgstr "" + +#: common/db/fields.py:167 +msgid "Encrypt field using Secret Key" +msgstr "" + +#: common/db/fields.py:582 +msgid "" +"Invalid JSON data for JSONManyToManyField, should be like {'type': 'all'} or " +"{'type': 'ids', 'ids': []} or {'type': 'attrs', 'attrs': [{'name': 'ip', " +"'match': 'exact', 'value': '1.1.1.1'}}" +msgstr "" + +#: common/db/fields.py:589 +msgid "Invalid type, should be \"all\", \"ids\" or \"attrs\"" +msgstr "" + +#: common/db/fields.py:592 +msgid "Invalid ids for ids, should be a list" +msgstr "" + +#: common/db/fields.py:594 common/db/fields.py:599 +#: common/serializers/fields.py:133 tickets/serializers/ticket/common.py:58 +#: xpack/plugins/cloud/serializers/account_attrs.py:56 +#: xpack/plugins/cloud/serializers/account_attrs.py:79 +#: xpack/plugins/cloud/serializers/account_attrs.py:150 +msgid "This field is required." +msgstr "" + +#: common/db/fields.py:597 common/db/fields.py:602 +msgid "Invalid attrs, should be a list of dict" +msgstr "" + +#: common/db/fields.py:604 +msgid "Invalid attrs, should be has name and value" +msgstr "" + +#: common/db/mixins.py:32 +msgid "is discard" +msgstr "" + +#: common/db/mixins.py:33 +msgid "discard time" +msgstr "" + +#: common/db/models.py:33 users/models/user.py:918 +msgid "Updated by" +msgstr "" + +#: common/db/validators.py:9 +msgid "Invalid port range, should be like and within {}-{}" +msgstr "" + +#: common/drf/exc_handlers.py:26 +msgid "Object" +msgstr "" + +#: common/drf/metadata.py:127 +msgid "Org ID" +msgstr "" + +#: common/drf/parsers/base.py:21 +msgid "The file content overflowed (The maximum length `{}` bytes)" +msgstr "" + +#: common/drf/parsers/base.py:199 +msgid "Parse file error: {}" +msgstr "" + +#: common/drf/parsers/excel.py:14 +msgid "Invalid excel file" +msgstr "" + +#: common/drf/renders/base.py:208 +msgid "" +"{} - The encryption password has not been set - please go to personal " +"information -> file encryption password to set the encryption password" +msgstr "" + +#: common/exceptions.py:15 +#, python-format +msgid "%s object does not exist." +msgstr "" + +#: common/exceptions.py:25 +msgid "Someone else is doing this. Please wait for complete" +msgstr "" + +#: common/exceptions.py:30 +msgid "Your request timeout" +msgstr "" + +#: common/exceptions.py:35 +msgid "M2M reverse not allowed" +msgstr "" + +#: common/exceptions.py:41 +msgid "Is referenced by other objects and cannot be deleted" +msgstr "" + +#: common/exceptions.py:51 +msgid "This action require confirm current user" +msgstr "" + +#: common/exceptions.py:59 +msgid "Unexpect error occur" +msgstr "" + +#: common/plugins/es.py:31 +msgid "Invalid elasticsearch config" +msgstr "" + +#: common/plugins/es.py:36 +msgid "Not Support Elasticsearch8" +msgstr "" + +#: common/sdk/im/exceptions.py:23 +msgid "Network error, please contact system administrator" +msgstr "" + +#: common/sdk/im/slack/__init__.py:77 +msgid "Unknown error occur" +msgstr "" + +#: common/sdk/im/wecom/__init__.py:16 +msgid "WeCom error, please contact system administrator" +msgstr "" + +#: common/sdk/sms/alibaba.py:56 +msgid "Signature does not match" +msgstr "" + +#: common/sdk/sms/cmpp2.py:44 +msgid "sp_id is 6 bits" +msgstr "" + +#: common/sdk/sms/cmpp2.py:214 +msgid "Failed to connect to the CMPP gateway server, err: {}" +msgstr "" + +#: common/sdk/sms/custom_file.py:41 +msgid "The custom sms file is invalid" +msgstr "" + +#: common/sdk/sms/custom_file.py:47 +#, python-format +msgid "SMS sending failed[%s]: %s" +msgstr "" + +#: common/sdk/sms/endpoint.py:16 +msgid "Alibaba cloud" +msgstr "" + +#: common/sdk/sms/endpoint.py:17 +msgid "Tencent cloud" +msgstr "" + +#: common/sdk/sms/endpoint.py:18 xpack/plugins/cloud/const.py:13 +msgid "Huawei Cloud" +msgstr "" + +#: common/sdk/sms/endpoint.py:19 +msgid "CMPP v2.0" +msgstr "" + +#: common/sdk/sms/endpoint.py:21 +msgid "Custom type (File)" +msgstr "" + +#: common/sdk/sms/endpoint.py:32 +msgid "SMS provider not support: {}" +msgstr "" + +#: common/sdk/sms/endpoint.py:54 +msgid "SMS verification code signature or template invalid" +msgstr "" + +#: common/sdk/sms/exceptions.py:8 +msgid "The verification code has expired. Please resend it" +msgstr "" + +#: common/sdk/sms/exceptions.py:13 +msgid "The verification code is incorrect" +msgstr "" + +#: common/sdk/sms/exceptions.py:18 +msgid "Please wait {} seconds before sending" +msgstr "" + +#: common/serializers/common.py:90 +msgid "Children" +msgstr "" + +#: common/serializers/fields.py:134 +#, python-brace-format +msgid "Invalid pk \"{pk_value}\" - object does not exist." +msgstr "" + +#: common/serializers/fields.py:135 +#, python-brace-format +msgid "Incorrect type. Expected pk value, received {data_type}." +msgstr "" + +#: common/serializers/fields.py:209 +msgid "Invalid data type, should be list" +msgstr "" + +#: common/serializers/fields.py:224 +msgid "Invalid choice: {}" +msgstr "" + +#: common/serializers/mixin.py:409 +msgid "Labels" +msgstr "" + +#: common/tasks.py:31 common/utils/verify_code.py:16 +msgid "Send email" +msgstr "" + +#: common/tasks.py:58 +msgid "Send email attachment" +msgstr "" + +#: common/tasks.py:80 terminal/tasks.py:58 +msgid "Upload session replay to external storage" +msgstr "" + +#: common/utils/ip/geoip/utils.py:26 +msgid "Invalid ip" +msgstr "" + +#: common/utils/ip/utils.py:98 +msgid "Invalid address" +msgstr "" + +#: common/utils/translate.py:45 +#, python-format +msgid "Hello %s" +msgstr "" + +#: common/validators.py:16 +msgid "Special char not allowed" +msgstr "" + +#: common/validators.py:42 +msgid "Should not contains special characters" +msgstr "" + +#: common/validators.py:47 +msgid "The mobile phone number format is incorrect" +msgstr "" + +#: jumpserver/conf.py:459 +#, python-brace-format +msgid "The verification code is: {code}" +msgstr "" + +#: jumpserver/conf.py:464 +msgid "Create account successfully" +msgstr "" + +#: jumpserver/conf.py:466 +msgid "Your account has been created successfully" +msgstr "" + +#: jumpserver/context_processor.py:14 +msgid "JumpServer Open Source Bastion Host" +msgstr "" + +#: jumpserver/views/celery_flower.py:22 +msgid "

Flower service unavailable, check it

" +msgstr "" + +#: jumpserver/views/other.py:27 +msgid "" +"
Luna is a separately deployed program, you need to deploy Luna, koko, " +"configure nginx for url distribution,
If you see this page, " +"prove that you are not accessing the nginx listening port. Good luck." +msgstr "" + +#: jumpserver/views/other.py:72 +msgid "Websocket server run on port: {}, you should proxy it on nginx" +msgstr "" + +#: jumpserver/views/other.py:86 +msgid "" +"
Koko is a separately deployed program, you need to deploy Koko, " +"configure nginx for url distribution,
If you see this page, " +"prove that you are not accessing the nginx listening port. Good luck." +msgstr "" + +#: labels/apps.py:8 +msgid "App Labels" +msgstr "" + +#: labels/models.py:36 +msgid "Resource ID" +msgstr "" + +#: labels/models.py:41 +msgid "Labeled resource" +msgstr "" + +#: labels/serializers.py:22 +msgid "Resource count" +msgstr "" + +#: labels/serializers.py:28 +msgid "Cannot contain \":,\"" +msgstr "" + +#: labels/serializers.py:43 +msgid "Resource type" +msgstr "" + +#: notifications/apps.py:7 +msgid "App Notifications" +msgstr "" + +#: notifications/backends/__init__.py:13 +msgid "Site message" +msgstr "" + +#: notifications/models/notification.py:14 +msgid "receive backend" +msgstr "" + +#: notifications/models/notification.py:18 +msgid "User message" +msgstr "" + +#: notifications/models/notification.py:21 +msgid "{} subscription" +msgstr "" + +#: notifications/models/notification.py:34 +msgid "System message" +msgstr "" + +#: notifications/notifications.py:46 +msgid "Publish the station message" +msgstr "" + +#: ops/ansible/inventory.py:107 ops/models/job.py:65 +msgid "No account available" +msgstr "" + +#: ops/ansible/inventory.py:286 +msgid "Ansible disabled" +msgstr "" + +#: ops/ansible/inventory.py:302 +msgid "Skip hosts below:" +msgstr "" + +#: ops/api/celery.py:66 ops/api/celery.py:81 +msgid "Waiting task start" +msgstr "" + +#: ops/api/celery.py:262 +msgid "Task {} not found" +msgstr "" + +#: ops/api/celery.py:267 +msgid "Task {} args or kwargs error" +msgstr "" + +#: ops/api/job.py:81 +#, python-brace-format +msgid "" +"Asset ({asset}) must have at least one of the following protocols added: " +"SSH, SFTP, or WinRM" +msgstr "" + +#: ops/api/job.py:82 +#, python-brace-format +msgid "Asset ({asset}) authorization is missing SSH, SFTP, or WinRM protocol" +msgstr "" + +#: ops/api/job.py:83 +#, python-brace-format +msgid "Asset ({asset}) authorization lacks upload permissions" +msgstr "" + +#: ops/api/job.py:168 +msgid "Duplicate file exists" +msgstr "" + +#: ops/api/job.py:173 +#, python-brace-format +msgid "" +"File size exceeds maximum limit. Please select a file smaller than {limit}MB" +msgstr "" + +#: ops/api/job.py:237 +msgid "" +"The task is being created and cannot be interrupted. Please try again later." +msgstr "" + +#: ops/api/playbook.py:39 +msgid "Currently playbook is being used in a job" +msgstr "" + +#: ops/api/playbook.py:96 +msgid "Unsupported file content" +msgstr "" + +#: ops/api/playbook.py:98 ops/api/playbook.py:144 ops/api/playbook.py:192 +msgid "Invalid file path" +msgstr "" + +#: ops/api/playbook.py:170 +msgid "This file can not be rename" +msgstr "" + +#: ops/api/playbook.py:189 +msgid "File already exists" +msgstr "" + +#: ops/api/playbook.py:207 +msgid "File key is required" +msgstr "" + +#: ops/api/playbook.py:210 +msgid "This file can not be delete" +msgstr "" + +#: ops/apps.py:9 +msgid "App Ops" +msgstr "" + +#: ops/const.py:6 +msgid "Push" +msgstr "" + +#: ops/const.py:7 +msgid "Verify" +msgstr "" + +#: ops/const.py:8 +msgid "Collect" +msgstr "" + +#: ops/const.py:19 +msgid "Custom password" +msgstr "" + +#: ops/const.py:20 +msgid "All assets use the same random password" +msgstr "" + +#: ops/const.py:21 +msgid "All assets use different random password" +msgstr "" + +#: ops/const.py:33 +msgid "Blank" +msgstr "" + +#: ops/const.py:34 +msgid "VCS" +msgstr "" + +#: ops/const.py:38 ops/models/adhoc.py:44 +msgid "Adhoc" +msgstr "" + +#: ops/const.py:39 ops/models/job.py:149 +msgid "Playbook" +msgstr "" + +#: ops/const.py:40 +msgid "Upload File" +msgstr "" + +#: ops/const.py:44 +msgid "Privileged Only" +msgstr "" + +#: ops/const.py:45 +msgid "Privileged First" +msgstr "" + +#: ops/const.py:50 ops/const.py:61 +msgid "Shell" +msgstr "" + +#: ops/const.py:51 ops/const.py:62 +msgid "Powershell" +msgstr "" + +#: ops/const.py:52 ops/const.py:63 +msgid "Python" +msgstr "" + +#: ops/const.py:53 ops/const.py:64 +msgid "MySQL" +msgstr "" + +#: ops/const.py:54 ops/const.py:66 +msgid "PostgreSQL" +msgstr "" + +#: ops/const.py:55 ops/const.py:67 +msgid "SQLServer" +msgstr "" + +#: ops/const.py:56 ops/const.py:69 +msgid "Raw" +msgstr "" + +#: ops/const.py:57 +msgid "HUAWEI" +msgstr "" + +#: ops/const.py:65 +msgid "MariaDB" +msgstr "" + +#: ops/const.py:68 +msgid "Oracle" +msgstr "" + +#: ops/const.py:75 +msgid "Timeout" +msgstr "" + +#: ops/exception.py:6 +msgid "no valid program entry found." +msgstr "" + +#: ops/mixin.py:23 ops/mixin.py:102 settings/serializers/auth/ldap.py:66 +msgid "Periodic run" +msgstr "" + +#: ops/mixin.py:25 ops/mixin.py:88 ops/mixin.py:108 +#: settings/serializers/auth/ldap.py:73 +msgid "Interval" +msgstr "" + +#: ops/mixin.py:28 ops/mixin.py:86 ops/mixin.py:105 +#: settings/serializers/auth/ldap.py:70 +msgid "Crontab" +msgstr "" + +#: ops/mixin.py:110 +msgid "Run period" +msgstr "" + +#: ops/mixin.py:119 +msgid "* Please enter a valid crontab expression" +msgstr "" + +#: ops/mixin.py:126 +msgid "Range {} to {}" +msgstr "" + +#: ops/mixin.py:137 +msgid "Require interval or crontab setting" +msgstr "" + +#: ops/models/adhoc.py:21 +msgid "Pattern" +msgstr "" + +#: ops/models/adhoc.py:23 ops/models/job.py:146 +msgid "Module" +msgstr "" + +#: ops/models/adhoc.py:24 ops/models/celery.py:81 ops/models/job.py:144 +#: terminal/models/component/task.py:14 +msgid "Args" +msgstr "" + +#: ops/models/base.py:19 +msgid "Account policy" +msgstr "" + +#: ops/models/base.py:20 +msgid "Last execution" +msgstr "" + +#: ops/models/base.py:22 ops/serializers/job.py:17 +msgid "Date last run" +msgstr "" + +#: ops/models/base.py:51 ops/models/job.py:237 +#: xpack/plugins/cloud/models.py:202 +msgid "Result" +msgstr "" + +#: ops/models/base.py:52 ops/models/job.py:238 +msgid "Summary" +msgstr "" + +#: ops/models/celery.py:16 +msgid "Date last publish" +msgstr "" + +#: ops/models/celery.py:70 +msgid "Celery Task" +msgstr "" + +#: ops/models/celery.py:73 +msgid "Can view task monitor" +msgstr "" + +#: ops/models/celery.py:82 terminal/models/component/task.py:15 +msgid "Kwargs" +msgstr "" + +#: ops/models/celery.py:84 terminal/models/session/sharing.py:128 +#: tickets/const.py:25 +msgid "Finished" +msgstr "" + +#: ops/models/celery.py:87 +msgid "Date published" +msgstr "" + +#: ops/models/celery.py:112 +msgid "Celery Task Execution" +msgstr "" + +#: ops/models/job.py:147 +msgid "Chdir" +msgstr "" + +#: ops/models/job.py:148 +msgid "Timeout (Seconds)" +msgstr "" + +#: ops/models/job.py:153 +msgid "Use Parameter Define" +msgstr "" + +#: ops/models/job.py:154 +msgid "Parameters define" +msgstr "" + +#: ops/models/job.py:155 +msgid "Runas" +msgstr "" + +#: ops/models/job.py:157 +msgid "Runas policy" +msgstr "" + +#: ops/models/job.py:221 terminal/notifications.py:174 +msgid "Job" +msgstr "" + +#: ops/models/job.py:244 +msgid "Material" +msgstr "" + +#: ops/models/job.py:246 +msgid "Material Type" +msgstr "" + +#: ops/models/job.py:544 +msgid "Job Execution" +msgstr "" + +#: ops/models/playbook.py:33 +msgid "CreateMethod" +msgstr "" + +#: ops/models/playbook.py:34 +msgid "VCS URL" +msgstr "" + +#: ops/notifications.py:19 +msgid "Server performance" +msgstr "" + +#: ops/notifications.py:25 +msgid "Terminal health check warning" +msgstr "" + +#: ops/notifications.py:70 +#, python-brace-format +msgid "The terminal is offline: {name}" +msgstr "" + +#: ops/notifications.py:75 +#, python-brace-format +msgid "Disk used more than {max_threshold}%: => {value}" +msgstr "" + +#: ops/notifications.py:80 +#, python-brace-format +msgid "Memory used more than {max_threshold}%: => {value}" +msgstr "" + +#: ops/notifications.py:85 +#, python-brace-format +msgid "CPU load more than {max_threshold}: => {value}" +msgstr "" + +#: ops/serializers/celery.py:33 +msgid "Execution cycle" +msgstr "" + +#: ops/serializers/celery.py:35 +msgid "Next execution time" +msgstr "" + +#: ops/serializers/job.py:15 +msgid "Execute after saving" +msgstr "" + +#: ops/serializers/job.py:52 +msgid "Average time cost" +msgstr "" + +#: ops/serializers/job.py:72 +msgid "Job type" +msgstr "" + +#: ops/serializers/job.py:75 terminal/serializers/session.py:56 +msgid "Is finished" +msgstr "" + +#: ops/serializers/job.py:76 +#: settings/templates/ldap/_msg_import_ldap_user.html:7 +msgid "Time cost" +msgstr "" + +#: ops/serializers/job.py:90 +msgid "You do not have permission for the current job." +msgstr "" + +#: ops/tasks.py:38 +msgid "Run ansible task" +msgstr "" + +#: ops/tasks.py:72 +msgid "Run ansible task execution" +msgstr "" + +#: ops/tasks.py:94 +msgid "Clear celery periodic tasks" +msgstr "" + +#: ops/tasks.py:115 +msgid "Create or update periodic tasks" +msgstr "" + +#: ops/tasks.py:123 +msgid "Periodic check service performance" +msgstr "" + +#: ops/tasks.py:129 +msgid "Clean up unexpected jobs" +msgstr "" + +#: ops/tasks.py:136 +msgid "Clean job_execution db record" +msgstr "" + +#: ops/templates/ops/celery_task_log.html:4 +msgid "Task log" +msgstr "" + +#: ops/variables.py:24 +msgid "The current user`s username of JumpServer" +msgstr "" + +#: ops/variables.py:25 +msgid "The id of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:26 +msgid "The type of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:27 +msgid "The category of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:28 +msgid "The name of the asset in the JumpServer" +msgstr "" + +#: ops/variables.py:29 +msgid "Address used to connect this asset in JumpServer" +msgstr "" + +#: ops/variables.py:30 +msgid "Port used to connect this asset in JumpServer" +msgstr "" + +#: ops/variables.py:31 +msgid "ID of the job" +msgstr "" + +#: ops/variables.py:32 +msgid "Name of the job" +msgstr "" + +#: orgs/api.py:61 +msgid "The current organization ({}) cannot be deleted" +msgstr "" + +#: orgs/api.py:66 +msgid "" +"LDAP synchronization is set to the current organization. Please switch to " +"another organization before deleting" +msgstr "" + +#: orgs/api.py:76 +msgid "The organization have resource ({}) cannot be deleted" +msgstr "" + +#: orgs/apps.py:7 +msgid "App Organizations" +msgstr "" + +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:91 +#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/serializers/rolebinding.py:44 settings/serializers/auth/ldap.py:63 +#: terminal/templates/terminal/_msg_command_warning.html:21 +#: terminal/templates/terminal/_msg_session_sharing.html:14 +#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:60 +msgid "Organization" +msgstr "" + +#: orgs/mixins/serializers.py:26 rbac/serializers/rolebinding.py:27 +msgid "Org name" +msgstr "" + +#: orgs/models.py:14 +msgid "GLOBAL" +msgstr "" + +#: orgs/models.py:16 +msgid "DEFAULT" +msgstr "" + +#: orgs/models.py:18 +msgid "SYSTEM" +msgstr "" + +#: orgs/models.py:83 rbac/models/role.py:36 settings/models.py:185 +#: terminal/models/applet/applet.py:41 +msgid "Builtin" +msgstr "" + +#: orgs/models.py:93 +msgid "Can view root org" +msgstr "" + +#: orgs/models.py:94 +msgid "Can view all joined org" +msgstr "" + +#: orgs/models.py:236 +msgid "Can not delete virtual org" +msgstr "" + +#: orgs/serializers.py:10 perms/serializers/permission.py:38 +#: rbac/serializers/role.py:27 users/serializers/group.py:54 +msgid "Users amount" +msgstr "" + +#: orgs/serializers.py:11 +msgid "User groups amount" +msgstr "" + +#: orgs/serializers.py:14 perms/serializers/permission.py:41 +msgid "Nodes amount" +msgstr "" + +#: orgs/serializers.py:15 +msgid "Domains amount" +msgstr "" + +#: orgs/serializers.py:16 +msgid "Gateways amount" +msgstr "" + +#: orgs/serializers.py:18 +msgid "Asset permissions amount" +msgstr "" + +#: orgs/tasks.py:9 +msgid "Refresh organization cache" +msgstr "" + +#: perms/apps.py:9 +msgid "App Permissions" +msgstr "" + +#: perms/const.py:12 +msgid "Connect (All protocols)" +msgstr "" + +#: perms/const.py:13 +msgid "Upload (RDP, SFTP)" +msgstr "" + +#: perms/const.py:14 +msgid "Download (RDP, SFTP)" +msgstr "" + +#: perms/const.py:15 +msgid "Copy (RDP, VNC)" +msgstr "" + +#: perms/const.py:16 +msgid "Paste (RDP, VNC)" +msgstr "" + +#: perms/const.py:17 +msgid "Delete (SFTP)" +msgstr "" + +#: perms/const.py:18 +msgid "Share (SSH)" +msgstr "" + +#: perms/const.py:28 +msgid "Transfer" +msgstr "" + +#: perms/const.py:29 +msgid "Clipboard" +msgstr "" + +#: perms/models/asset_permission.py:89 +msgid "Asset permission" +msgstr "" + +#: perms/models/perm_node.py:68 +msgid "Ungrouped" +msgstr "" + +#: perms/models/perm_node.py:70 +msgid "Favorite" +msgstr "" + +#: perms/models/perm_node.py:121 +msgid "Permed asset" +msgstr "" + +#: perms/models/perm_node.py:123 +msgid "Can view my assets" +msgstr "" + +#: perms/models/perm_node.py:124 +msgid "Can view user assets" +msgstr "" + +#: perms/models/perm_node.py:125 +msgid "Can view usergroup assets" +msgstr "" + +#: perms/models/perm_node.py:136 +msgid "Permed account" +msgstr "" + +#: perms/notifications.py:12 perms/notifications.py:44 +msgid "today" +msgstr "" + +#: perms/notifications.py:12 perms/notifications.py:44 +#: settings/serializers/feature.py:118 +msgid "day" +msgstr "" + +#: perms/notifications.py:15 +msgid "You permed assets is about to expire" +msgstr "" + +#: perms/notifications.py:20 +msgid "permed assets" +msgstr "" + +#: perms/notifications.py:59 +msgid "Asset permissions is about to expire" +msgstr "" + +#: perms/notifications.py:64 +msgid "asset permissions of organization {}" +msgstr "" + +#: perms/serializers/permission.py:34 users/serializers/user.py:173 +msgid "Groups" +msgstr "" + +#: perms/serializers/permission.py:39 +msgid "Groups amount" +msgstr "" + +#: perms/tasks.py:27 +msgid "Check asset permission expired" +msgstr "" + +#: perms/tasks.py:40 +msgid "Send asset permission expired notification" +msgstr "" + +#: perms/templates/perms/_msg_item_permissions_expire.html:7 +#: perms/templates/perms/_msg_permed_items_expire.html:7 +#, python-format +msgid "" +"\n" +" The following %(item_type)s will expire in %(count)s\n" +" " +msgstr "" + +#: rbac/api/role.py:35 +msgid "Internal role, can't be destroy" +msgstr "" + +#: rbac/api/role.py:40 +msgid "The role has been bound to users, can't be destroy" +msgstr "" + +#: rbac/api/role.py:105 +msgid "Internal role, can't be update" +msgstr "" + +#: rbac/api/rolebinding.py:45 +msgid "{} at least one system role" +msgstr "" + +#: rbac/apps.py:7 +msgid "App RBAC" +msgstr "" + +#: rbac/builtin.py:115 +msgid "SystemAdmin" +msgstr "" + +#: rbac/builtin.py:118 +msgid "SystemAuditor" +msgstr "" + +#: rbac/builtin.py:121 +msgid "SystemComponent" +msgstr "" + +#: rbac/builtin.py:127 +msgid "OrgAdmin" +msgstr "" + +#: rbac/builtin.py:130 +msgid "OrgAuditor" +msgstr "" + +#: rbac/builtin.py:133 +msgid "OrgUser" +msgstr "" + +#: rbac/models/menu.py:13 +msgid "Menu permission" +msgstr "" + +#: rbac/models/menu.py:15 +msgid "Can view console view" +msgstr "" + +#: rbac/models/menu.py:16 +msgid "Can view audit view" +msgstr "" + +#: rbac/models/menu.py:17 +msgid "Can view workbench view" +msgstr "" + +#: rbac/models/menu.py:18 +msgid "Can view web terminal" +msgstr "" + +#: rbac/models/menu.py:19 +msgid "Can view file manager" +msgstr "" + +#: rbac/models/menu.py:20 +msgid "Can view System Tools" +msgstr "" + +#: rbac/models/permission.py:78 rbac/models/role.py:34 +msgid "Permissions" +msgstr "" + +#: rbac/models/role.py:31 rbac/models/rolebinding.py:46 +#: rbac/serializers/role.py:12 settings/serializers/auth/oauth2.py:36 +msgid "Scope" +msgstr "" + +#: rbac/models/role.py:46 rbac/models/rolebinding.py:52 +#: users/models/user.py:884 +msgid "Role" +msgstr "" + +#: rbac/models/role.py:144 +msgid "System role" +msgstr "" + +#: rbac/models/role.py:152 +msgid "Organization role" +msgstr "" + +#: rbac/models/rolebinding.py:62 +msgid "Role binding" +msgstr "" + +#: rbac/models/rolebinding.py:161 +msgid "All organizations" +msgstr "" + +#: rbac/models/rolebinding.py:193 +msgid "" +"User last role in org, can not be delete, you can remove user from org " +"instead" +msgstr "" + +#: rbac/models/rolebinding.py:200 +msgid "Organization role binding" +msgstr "" + +#: rbac/models/rolebinding.py:215 +msgid "System role binding" +msgstr "" + +#: rbac/serializers/permission.py:25 users/serializers/profile.py:108 +msgid "Perms" +msgstr "" + +#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:34 +#: terminal/models/virtualapp/virtualapp.py:20 +msgid "Display name" +msgstr "" + +#: rbac/serializers/rolebinding.py:60 +msgid "Has bound this role" +msgstr "" + +#: rbac/tree.py:17 rbac/tree.py:18 +msgid "All permissions" +msgstr "" + +#: rbac/tree.py:24 +msgid "Console view" +msgstr "" + +#: rbac/tree.py:25 +msgid "Workbench view" +msgstr "" + +#: rbac/tree.py:26 +msgid "Audit view" +msgstr "" + +#: rbac/tree.py:27 settings/models.py:161 +msgid "System setting" +msgstr "" + +#: rbac/tree.py:37 +msgid "Session audits" +msgstr "" + +#: rbac/tree.py:49 +msgid "Cloud import" +msgstr "" + +#: rbac/tree.py:50 +msgid "Backup account" +msgstr "" + +#: rbac/tree.py:51 +msgid "Gather account" +msgstr "" + +#: rbac/tree.py:53 +msgid "Asset change auth" +msgstr "" + +#: rbac/tree.py:54 +msgid "Terminal setting" +msgstr "" + +#: rbac/tree.py:55 settings/serializers/feature.py:127 +msgid "Job center" +msgstr "" + +#: rbac/tree.py:56 +msgid "My assets" +msgstr "" + +#: rbac/tree.py:57 +msgid "App ops" +msgstr "" + +#: rbac/tree.py:58 terminal/models/applet/applet.py:52 +#: terminal/models/applet/applet.py:317 terminal/models/applet/host.py:30 +#: terminal/serializers/applet.py:15 +msgid "Applet" +msgstr "" + +#: rbac/tree.py:128 +msgid "App organizations" +msgstr "" + +#: rbac/tree.py:129 +msgid "Ticket comment" +msgstr "" + +#: rbac/tree.py:130 settings/serializers/feature.py:109 +#: tickets/models/ticket/general.py:305 +msgid "Ticket" +msgstr "" + +#: rbac/tree.py:131 +msgid "Common setting" +msgstr "" + +#: rbac/tree.py:132 +msgid "View permission tree" +msgstr "" + +#: settings/api/chat.py:40 +msgid "Chat AI is not enabled" +msgstr "" + +#: settings/api/chat.py:79 settings/api/dingtalk.py:31 +#: settings/api/feishu.py:36 settings/api/slack.py:34 settings/api/sms.py:160 +#: settings/api/vault.py:40 settings/api/wecom.py:37 +msgid "Test success" +msgstr "" + +#: settings/api/email.py:22 +msgid "Test mail sent to {}, please check" +msgstr "" + +#: settings/api/ldap.py:89 +msgid "" +"Users are not synchronized, please click the user synchronization button" +msgstr "" + +#: settings/api/sms.py:142 +msgid "Invalid SMS platform" +msgstr "" + +#: settings/api/sms.py:148 +msgid "test_phone is required" +msgstr "" + +#: settings/apps.py:7 +msgid "App Settings" +msgstr "" + +#: settings/models.py:37 users/models/preference.py:14 +msgid "Encrypted" +msgstr "" + +#: settings/models.py:163 +msgid "Can change email setting" +msgstr "" + +#: settings/models.py:164 +msgid "Can change auth setting" +msgstr "" + +#: settings/models.py:165 +msgid "Can change auth ops" +msgstr "" + +#: settings/models.py:166 +msgid "Can change auth ticket" +msgstr "" + +#: settings/models.py:167 +msgid "Can change virtual app setting" +msgstr "" + +#: settings/models.py:168 +msgid "Can change auth announcement" +msgstr "" + +#: settings/models.py:169 +msgid "Can change vault setting" +msgstr "" + +#: settings/models.py:170 +msgid "Can change chat ai setting" +msgstr "" + +#: settings/models.py:171 +msgid "Can change system msg sub setting" +msgstr "" + +#: settings/models.py:172 +msgid "Can change sms setting" +msgstr "" + +#: settings/models.py:173 +msgid "Can change security setting" +msgstr "" + +#: settings/models.py:174 +msgid "Can change clean setting" +msgstr "" + +#: settings/models.py:175 +msgid "Can change interface setting" +msgstr "" + +#: settings/models.py:176 +msgid "Can change license setting" +msgstr "" + +#: settings/models.py:177 +msgid "Can change terminal setting" +msgstr "" + +#: settings/models.py:178 +msgid "Can change other setting" +msgstr "" + +#: settings/models.py:188 +msgid "Chat prompt" +msgstr "" + +#: settings/notifications.py:23 +msgid "Notification of Synchronized LDAP User Task Results" +msgstr "" + +#: settings/serializers/auth/base.py:10 +msgid "Authentication" +msgstr "" + +#: settings/serializers/auth/base.py:12 +msgid "LDAP Auth" +msgstr "" + +#: settings/serializers/auth/base.py:13 +msgid "CAS Auth" +msgstr "" + +#: settings/serializers/auth/base.py:14 +msgid "OPENID Auth" +msgstr "" + +#: settings/serializers/auth/base.py:15 +msgid "SAML2 Auth" +msgstr "" + +#: settings/serializers/auth/base.py:16 +msgid "OAuth2 Auth" +msgstr "" + +#: settings/serializers/auth/base.py:17 +msgid "RADIUS Auth" +msgstr "" + +#: settings/serializers/auth/base.py:18 +msgid "DingTalk Auth" +msgstr "" + +#: settings/serializers/auth/base.py:19 +msgid "FeiShu Auth" +msgstr "" + +#: settings/serializers/auth/base.py:20 +msgid "Lark Auth" +msgstr "" + +#: settings/serializers/auth/base.py:21 +msgid "Slack Auth" +msgstr "" + +#: settings/serializers/auth/base.py:22 +msgid "WeCom Auth" +msgstr "" + +#: settings/serializers/auth/base.py:23 +msgid "SSO Auth" +msgstr "" + +#: settings/serializers/auth/base.py:24 +msgid "Passkey Auth" +msgstr "" + +#: settings/serializers/auth/base.py:27 +msgid "Forgot Password URL" +msgstr "" + +#: settings/serializers/auth/base.py:30 +msgid "Login redirection prompt" +msgstr "" + +#: settings/serializers/auth/cas.py:10 settings/serializers/auth/cas.py:12 +msgid "CAS" +msgstr "" + +#: settings/serializers/auth/cas.py:13 settings/serializers/auth/ldap.py:42 +#: settings/serializers/auth/oidc.py:54 +msgid "Server" +msgstr "" + +#: settings/serializers/auth/cas.py:16 +msgid "Proxy Server" +msgstr "" + +#: settings/serializers/auth/cas.py:18 settings/serializers/auth/oauth2.py:54 +#: settings/serializers/auth/saml2.py:33 +msgid "Logout completely" +msgstr "" + +#: settings/serializers/auth/cas.py:23 +msgid "Username attr" +msgstr "" + +#: settings/serializers/auth/cas.py:26 +msgid "Enable attributes map" +msgstr "" + +#: settings/serializers/auth/cas.py:28 settings/serializers/auth/ldap.py:58 +#: settings/serializers/auth/oauth2.py:56 settings/serializers/auth/oidc.py:37 +#: settings/serializers/auth/saml2.py:32 +msgid "User attribute" +msgstr "" + +#: settings/serializers/auth/cas.py:30 +msgid "Create user" +msgstr "" + +#: settings/serializers/auth/cas.py:31 +msgid "Automatically create a new user if not found." +msgstr "" + +#: settings/serializers/auth/dingtalk.py:15 +msgid "Dingtalk" +msgstr "" + +#: settings/serializers/auth/feishu.py:12 +msgid "Enable FeiShu Auth" +msgstr "" + +#: settings/serializers/auth/lark.py:12 +msgid "Enable Lark Auth" +msgstr "" + +#: settings/serializers/auth/ldap.py:39 settings/serializers/auth/ldap.py:93 +msgid "LDAP" +msgstr "" + +#: settings/serializers/auth/ldap.py:43 +msgid "eg: ldap://localhost:389" +msgstr "" + +#: settings/serializers/auth/ldap.py:45 +msgid "Bind DN" +msgstr "" + +#: settings/serializers/auth/ldap.py:50 +msgid "User OU" +msgstr "" + +#: settings/serializers/auth/ldap.py:51 +msgid "Use | split multi OUs" +msgstr "" + +#: settings/serializers/auth/ldap.py:54 +msgid "User search filter" +msgstr "" + +#: settings/serializers/auth/ldap.py:55 +#, python-format +msgid "Choice may be (cn|uid|sAMAccountName)=%(user)s)" +msgstr "" + +#: settings/serializers/auth/ldap.py:59 +msgid "" +"User attr map present how to map LDAP user attr to jumpserver, username,name," +"email is jumpserver attr" +msgstr "" + +#: settings/serializers/auth/ldap.py:77 +msgid "Connect timeout (s)" +msgstr "" + +#: settings/serializers/auth/ldap.py:82 +msgid "User DN cache timeout (s)" +msgstr "" + +#: settings/serializers/auth/ldap.py:84 +msgid "" +"Caching the User DN obtained during user login authentication can " +"effectivelyimprove the speed of user authentication., 0 means no cache" +msgstr "" + +#: settings/serializers/auth/ldap.py:88 +msgid "Search paged size (piece)" +msgstr "" + +#: settings/serializers/auth/oauth2.py:18 +#: settings/serializers/auth/oauth2.py:21 +msgid "OAuth2" +msgstr "" + +#: settings/serializers/auth/oauth2.py:24 +msgid "Logo" +msgstr "" + +#: settings/serializers/auth/oauth2.py:27 +msgid "Service provider" +msgstr "" + +#: settings/serializers/auth/oauth2.py:30 settings/serializers/auth/oidc.py:19 +msgid "Client Id" +msgstr "" + +#: settings/serializers/auth/oauth2.py:33 settings/serializers/auth/oidc.py:22 +#: xpack/plugins/cloud/serializers/account_attrs.py:38 +msgid "Client Secret" +msgstr "" + +#: settings/serializers/auth/oauth2.py:39 settings/serializers/auth/oidc.py:68 +msgid "Authorization endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:42 settings/serializers/auth/oidc.py:71 +msgid "Token endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:45 settings/serializers/auth/oidc.py:30 +#: settings/serializers/auth/sms.py:106 +msgid "Request method" +msgstr "" + +#: settings/serializers/auth/oauth2.py:49 settings/serializers/auth/oidc.py:77 +msgid "Userinfo endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:52 settings/serializers/auth/oidc.py:80 +msgid "End session endpoint" +msgstr "" + +#: settings/serializers/auth/oauth2.py:59 settings/serializers/auth/oidc.py:98 +#: settings/serializers/auth/saml2.py:34 +msgid "Always update user" +msgstr "" + +#: settings/serializers/auth/oidc.py:12 settings/serializers/auth/oidc.py:63 +msgid "OIDC" +msgstr "" + +#: settings/serializers/auth/oidc.py:16 +msgid "Base site URL" +msgstr "" + +#: settings/serializers/auth/oidc.py:32 +msgid "Share session" +msgstr "" + +#: settings/serializers/auth/oidc.py:34 +msgid "Ignore SSL verification" +msgstr "" + +#: settings/serializers/auth/oidc.py:38 +msgid "" +"User attr map present how to map OpenID user attr to jumpserver, username," +"name,email is jumpserver attr" +msgstr "" + +#: settings/serializers/auth/oidc.py:41 +msgid "Enable PKCE" +msgstr "" + +#: settings/serializers/auth/oidc.py:43 +msgid "Code challenge method" +msgstr "" + +#: settings/serializers/auth/oidc.py:51 +msgid "Use Keycloak" +msgstr "" + +#: settings/serializers/auth/oidc.py:57 +msgid "Realm name" +msgstr "" + +#: settings/serializers/auth/oidc.py:65 +msgid "Provider endpoint" +msgstr "" + +#: settings/serializers/auth/oidc.py:74 +msgid "JWKS endpoint" +msgstr "" + +#: settings/serializers/auth/oidc.py:83 +msgid "Signature algorithm" +msgstr "" + +#: settings/serializers/auth/oidc.py:86 +msgid "Signing key" +msgstr "" + +#: settings/serializers/auth/oidc.py:88 +msgid "Scopes" +msgstr "" + +#: settings/serializers/auth/oidc.py:90 +msgid "ID Token max age (s)" +msgstr "" + +#: settings/serializers/auth/oidc.py:93 +msgid "ID Token include claims" +msgstr "" + +#: settings/serializers/auth/oidc.py:95 +msgid "Use state" +msgstr "" + +#: settings/serializers/auth/oidc.py:96 +msgid "Use nonce" +msgstr "" + +#: settings/serializers/auth/passkey.py:12 +msgid "Only SSL domain can use passkey auth" +msgstr "" + +#: settings/serializers/auth/passkey.py:15 +msgid "FIDO Server ID" +msgstr "" + +#: settings/serializers/auth/passkey.py:17 +msgid "" +"The hostname can using passkey auth, If not set, will use request host and " +"the request host in DOMAINS, If multiple domains, use comma to separate" +msgstr "" + +#: settings/serializers/auth/passkey.py:22 +msgid "FIDO Server name" +msgstr "" + +#: settings/serializers/auth/radius.py:13 +#: settings/serializers/auth/radius.py:15 +msgid "Radius" +msgstr "" + +#: settings/serializers/auth/radius.py:21 +msgid "OTP in Radius" +msgstr "" + +#: settings/serializers/auth/saml2.py:10 settings/serializers/auth/saml2.py:13 +msgid "SAML2" +msgstr "" + +#: settings/serializers/auth/saml2.py:16 +msgid "IDP Metadata URL" +msgstr "" + +#: settings/serializers/auth/saml2.py:19 +msgid "IDP Metadata XML" +msgstr "" + +#: settings/serializers/auth/saml2.py:22 +msgid "SP advanced settings" +msgstr "" + +#: settings/serializers/auth/saml2.py:26 +msgid "SP private key" +msgstr "" + +#: settings/serializers/auth/saml2.py:30 +msgid "SP cert" +msgstr "" + +#: settings/serializers/auth/sms.py:19 +msgid "SMS provider / Protocol" +msgstr "" + +#: settings/serializers/auth/sms.py:22 +msgid "SMS code length" +msgstr "" + +#: settings/serializers/auth/sms.py:27 settings/serializers/auth/sms.py:49 +#: settings/serializers/auth/sms.py:57 settings/serializers/auth/sms.py:66 +#: settings/serializers/auth/sms.py:77 settings/serializers/msg.py:83 +msgid "Signature" +msgstr "" + +#: settings/serializers/auth/sms.py:28 settings/serializers/auth/sms.py:50 +#: settings/serializers/auth/sms.py:58 settings/serializers/auth/sms.py:67 +msgid "Template code" +msgstr "" + +#: settings/serializers/auth/sms.py:35 +msgid "Test phone" +msgstr "" + +#: settings/serializers/auth/sms.py:64 +msgid "App Access Address" +msgstr "" + +#: settings/serializers/auth/sms.py:65 +msgid "Signature channel number" +msgstr "" + +#: settings/serializers/auth/sms.py:73 +msgid "Enterprise code" +msgstr "" + +#: settings/serializers/auth/sms.py:74 +msgid "Shared secret" +msgstr "" + +#: settings/serializers/auth/sms.py:75 +msgid "Original number" +msgstr "" + +#: settings/serializers/auth/sms.py:76 +msgid "Business type" +msgstr "" + +#: settings/serializers/auth/sms.py:80 +#, python-brace-format +msgid "" +"Template need contain {code} and Signature + template length does not exceed " +"67 words. For example, your verification code is {code}, which is valid for " +"5 minutes. Please do not disclose it to others." +msgstr "" + +#: settings/serializers/auth/sms.py:89 +#, python-brace-format +msgid "The template needs to contain {code}" +msgstr "" + +#: settings/serializers/auth/sms.py:92 +msgid "Signature + Template must not exceed 65 words" +msgstr "" + +#: settings/serializers/auth/sms.py:101 +msgid "URL" +msgstr "" + +#: settings/serializers/auth/sso.py:16 +msgid "Enable SSO auth" +msgstr "" + +#: settings/serializers/auth/sso.py:17 +msgid "Other service can using SSO token login to JumpServer without password" +msgstr "" + +#: settings/serializers/auth/sso.py:20 +msgid "SSO auth key TTL" +msgstr "" + +#: settings/serializers/auth/sso.py:20 +#: xpack/plugins/cloud/serializers/account_attrs.py:200 +msgid "Unit: second" +msgstr "" + +#: settings/serializers/basic.py:11 +msgid "Site URL" +msgstr "" + +#: settings/serializers/basic.py:13 +msgid "" +"External URL, email links or other system callbacks are used to access it, " +"eg: http://dev.jumpserver.org:8080" +msgstr "" + +#: settings/serializers/basic.py:18 +msgid "User guide url" +msgstr "" + +#: settings/serializers/basic.py:19 +msgid "User first login update profile done redirect to it" +msgstr "" + +#: settings/serializers/basic.py:22 +msgid "Global organization" +msgstr "" + +#: settings/serializers/basic.py:23 +msgid "The name of global organization to display" +msgstr "" + +#: settings/serializers/basic.py:26 +msgid "Help Docs URL" +msgstr "" + +#: settings/serializers/basic.py:27 +msgid "default: http://docs.jumpserver.org" +msgstr "" + +#: settings/serializers/basic.py:30 +msgid "Help Support URL" +msgstr "" + +#: settings/serializers/basic.py:31 +msgid "default: http://www.jumpserver.org/support/" +msgstr "" + +#: settings/serializers/basic.py:44 +msgid "Organization name already exists" +msgstr "" + +#: settings/serializers/cleaning.py:11 +msgid "Period clean" +msgstr "" + +#: settings/serializers/cleaning.py:15 +msgid "Login log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:19 +msgid "Task log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:23 +msgid "Operate log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:27 +msgid "password change log keep days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:31 +msgid "FTP log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:35 +msgid "Cloud sync task history retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:39 +msgid "job execution retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:43 +msgid "Activity log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:46 +msgid "Session log retention days (day)" +msgstr "" + +#: settings/serializers/cleaning.py:48 +msgid "" +"Session, record, command will be delete if more than duration, only in " +"database, OSS will not be affected." +msgstr "" + +#: settings/serializers/feature.py:18 settings/serializers/msg.py:68 +msgid "Subject" +msgstr "" + +#: settings/serializers/feature.py:22 +msgid "More URL" +msgstr "" + +#: settings/serializers/feature.py:36 settings/serializers/feature.py:38 +#: settings/serializers/feature.py:39 +msgid "Announcement" +msgstr "" + +#: settings/serializers/feature.py:46 +msgid "Vault" +msgstr "" + +#: settings/serializers/feature.py:55 +msgid "Mount Point" +msgstr "" + +#: settings/serializers/feature.py:60 +msgid "Historical accounts retained count" +msgstr "" + +#: settings/serializers/feature.py:62 +msgid "" +"If the specific value is less than 999, the system will automatically " +"perform a task every night: check and delete historical accounts that exceed " +"the predetermined number. If the value reaches or exceeds 999, no historical " +"account deletion will be performed." +msgstr "" + +#: settings/serializers/feature.py:71 settings/serializers/feature.py:75 +msgid "Chat AI" +msgstr "" + +#: settings/serializers/feature.py:78 +msgid "Base Url" +msgstr "" + +#: settings/serializers/feature.py:81 templates/_header_bar.html:96 +msgid "API Key" +msgstr "" + +#: settings/serializers/feature.py:87 +msgid "GPT Model" +msgstr "" + +#: settings/serializers/feature.py:111 +msgid "Enable tickets" +msgstr "" + +#: settings/serializers/feature.py:112 +msgid "No login approval" +msgstr "" + +#: settings/serializers/feature.py:115 +msgid "Default period" +msgstr "" + +#: settings/serializers/feature.py:118 +msgid "hour" +msgstr "" + +#: settings/serializers/feature.py:119 +msgid "Default unit" +msgstr "" + +#: settings/serializers/feature.py:124 +msgid "Feature" +msgstr "" + +#: settings/serializers/feature.py:128 +msgid "Allow user run batch command or not using ansible" +msgstr "" + +#: settings/serializers/feature.py:132 +msgid "Command blacklist" +msgstr "" + +#: settings/serializers/feature.py:133 +msgid "Commands that are not allowed execute." +msgstr "" + +#: settings/serializers/feature.py:138 settings/serializers/feature.py:141 +#: terminal/models/virtualapp/provider.py:17 +#: terminal/models/virtualapp/virtualapp.py:36 +#: terminal/models/virtualapp/virtualapp.py:97 +#: terminal/serializers/virtualapp.py:32 +msgid "Virtual app" +msgstr "" + +#: settings/serializers/msg.py:25 +msgid "SMTP" +msgstr "" + +#: settings/serializers/msg.py:26 +msgid "EXCHANGE" +msgstr "" + +#: settings/serializers/msg.py:36 +msgid "Tips: Some provider use token except password" +msgstr "" + +#: settings/serializers/msg.py:39 +msgid "Sender" +msgstr "" + +#: settings/serializers/msg.py:40 +msgid "Tips: Send mail account, default SMTP account as the send account" +msgstr "" + +#: settings/serializers/msg.py:43 +msgid "Test recipient" +msgstr "" + +#: settings/serializers/msg.py:44 +msgid "Tips: Used only as a test mail recipient" +msgstr "" + +#: settings/serializers/msg.py:48 +msgid "If SMTP port is 465, may be select" +msgstr "" + +#: settings/serializers/msg.py:51 +msgid "Use TLS" +msgstr "" + +#: settings/serializers/msg.py:52 +msgid "If SMTP port is 587, may be select" +msgstr "" + +#: settings/serializers/msg.py:55 +msgid "Subject prefix" +msgstr "" + +#: settings/serializers/msg.py:58 +msgid "Email suffix" +msgstr "" + +#: settings/serializers/msg.py:59 +msgid "" +"This is used by default if no email is returned during SSO authentication" +msgstr "" + +#: settings/serializers/msg.py:69 +msgid "" +"Tips: When creating a user, send the subject of the email (eg:Create account " +"successfully)" +msgstr "" + +#: settings/serializers/msg.py:73 +msgid "Honorific" +msgstr "" + +#: settings/serializers/msg.py:74 +msgid "Tips: When creating a user, send the honorific of the email (eg:Hello)" +msgstr "" + +#: settings/serializers/msg.py:80 +#, python-brace-format +msgid "" +"Tips: When creating a user, send the content of the email, support " +"{username} {name} {email} label" +msgstr "" + +#: settings/serializers/msg.py:84 +msgid "Tips: Email signature (eg:jumpserver)" +msgstr "" + +#: settings/serializers/other.py:8 +msgid "More..." +msgstr "" + +#: settings/serializers/other.py:11 +msgid "Perm ungroup node" +msgstr "" + +#: settings/serializers/other.py:12 +msgid "Perm single to ungroup node" +msgstr "" + +#: settings/serializers/security.py:17 +msgid "User password expiration (day)" +msgstr "" + +#: settings/serializers/security.py:19 +msgid "" +"If the user does not update the password during the time, the user password " +"will expire failure;The password expiration reminder mail will be automatic " +"sent to the user by system within 5 days (daily) before the password expires" +msgstr "" + +#: settings/serializers/security.py:26 +msgid "Recent password count" +msgstr "" + +#: settings/serializers/security.py:28 +msgid "" +"Tip: When the user resets the password, it cannot be the previous n " +"historical passwords of the user" +msgstr "" + +#: settings/serializers/security.py:34 +msgid "Minimum length (User)" +msgstr "" + +#: settings/serializers/security.py:38 +msgid "Minimum length (Admin)" +msgstr "" + +#: settings/serializers/security.py:47 +msgid "Digits" +msgstr "" + +#: settings/serializers/security.py:50 +msgid "Special characters" +msgstr "" + +#: settings/serializers/security.py:55 +msgid "" +"If the user has failed to log in for a limited number of times, no login is " +"allowed during this time interval." +msgstr "" + +#: settings/serializers/security.py:63 settings/serializers/security.py:73 +msgid "Login failures count" +msgstr "" + +#: settings/serializers/security.py:67 settings/serializers/security.py:77 +msgid "Login failure period (minute)" +msgstr "" + +#: settings/serializers/security.py:81 +msgid "Login IP whitelist" +msgstr "" + +#: settings/serializers/security.py:86 +msgid "Login IP blacklist" +msgstr "" + +#: settings/serializers/security.py:91 +msgid "Only single device login" +msgstr "" + +#: settings/serializers/security.py:92 +msgid "" +"After the user logs in on the new device, other logged-in devices will " +"automatically log out" +msgstr "" + +#: settings/serializers/security.py:95 +msgid "Only exist user login" +msgstr "" + +#: settings/serializers/security.py:97 +msgid "" +"If enabled, non-existent users will not be allowed to log in; if disabled, " +"users of other authentication methods except local authentication methods " +"are allowed to log in and automatically create users (if the user does not " +"exist)" +msgstr "" + +#: settings/serializers/security.py:103 +msgid "Only from source login" +msgstr "" + +#: settings/serializers/security.py:105 +msgid "" +"If it is enabled, the user will only authenticate to the source when logging " +"in; if it is disabled, the user will authenticate all the enabled " +"authentication methods in a certain order when logging in, and as long as " +"one of the authentication methods is successful, they can log in directly" +msgstr "" + +#: settings/serializers/security.py:116 +msgid "Not enabled" +msgstr "" + +#: settings/serializers/security.py:117 +msgid "All users" +msgstr "" + +#: settings/serializers/security.py:118 +msgid "Only admin users" +msgstr "" + +#: settings/serializers/security.py:120 +msgid "Global MFA auth" +msgstr "" + +#: settings/serializers/security.py:124 +msgid "Third-party login MFA" +msgstr "" + +#: settings/serializers/security.py:125 +msgid "The third-party login modes include OIDC, CAS, and SAML2" +msgstr "" + +#: settings/serializers/security.py:128 +msgid "OTP issuer name" +msgstr "" + +#: settings/serializers/security.py:132 +msgid "OTP valid window" +msgstr "" + +#: settings/serializers/security.py:136 +msgid "MFA verify TTL" +msgstr "" + +#: settings/serializers/security.py:138 +msgid "" +"Unit: second, The verification MFA takes effect only when you view the " +"account password" +msgstr "" + +#: settings/serializers/security.py:143 +msgid "MFA in login page" +msgstr "" + +#: settings/serializers/security.py:144 +msgid "Eu security regulations(GDPR) require MFA to be on the login page" +msgstr "" + +#: settings/serializers/security.py:148 +msgid "Verify code TTL (second)" +msgstr "" + +#: settings/serializers/security.py:149 +msgid "Reset password and send SMS code expiration time" +msgstr "" + +#: settings/serializers/security.py:153 +msgid "Login dynamic code" +msgstr "" + +#: settings/serializers/security.py:154 +msgid "" +"The password and additional code are sent to a third party authentication " +"system for verification" +msgstr "" + +#: settings/serializers/security.py:158 +msgid "Login captcha" +msgstr "" + +#: settings/serializers/security.py:159 +msgid "Enable captcha to prevent robot authentication" +msgstr "" + +#: settings/serializers/security.py:162 +msgid "Suspicious Login Verification" +msgstr "" + +#: settings/serializers/security.py:164 +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 " +"a remote login reminder" +msgstr "" + +#: settings/serializers/security.py:170 +msgid "Auto Disable Threshold (day)" +msgstr "" + +#: settings/serializers/security.py:171 +msgid "" +"Detect infrequent users daily and disable them if they exceed the " +"predetermined time limit." +msgstr "" + +#: settings/serializers/security.py:191 +msgid "Watermark" +msgstr "" + +#: settings/serializers/security.py:192 +msgid "Enabled, the web session and replay contains watermark information" +msgstr "" + +#: settings/serializers/security.py:196 +msgid "Max idle time (minute)" +msgstr "" + +#: settings/serializers/security.py:197 +msgid "If idle time more than it, disconnect connection." +msgstr "" + +#: settings/serializers/security.py:200 +msgid "Session expire at browser closed" +msgstr "" + +#: settings/serializers/security.py:201 +msgid "Whether to expire the session when the user closes their browser." +msgstr "" + +#: settings/serializers/security.py:205 +msgid "Max online time (hour)" +msgstr "" + +#: settings/serializers/security.py:206 +msgid "If session connection time more than it, disconnect connection." +msgstr "" + +#: settings/serializers/security.py:209 +msgid "Remember manual auth" +msgstr "" + +#: settings/serializers/security.py:212 +#: terminal/templates/terminal/_msg_session_sharing.html:10 +msgid "Session share" +msgstr "" + +#: settings/serializers/security.py:213 +msgid "Enabled, Allows user active session to be shared with other users" +msgstr "" + +#: settings/serializers/security.py:219 +msgid "Insecure command alert" +msgstr "" + +#: settings/serializers/security.py:222 +msgid "Email recipient" +msgstr "" + +#: settings/serializers/security.py:223 +msgid "Multiple user using , split" +msgstr "" + +#: settings/serializers/settings.py:62 +#, python-format +msgid "[%s] %s" +msgstr "" + +#: settings/serializers/terminal.py:15 +msgid "Auto" +msgstr "" + +#: settings/serializers/terminal.py:22 +msgid "Terminal registration" +msgstr "" + +#: settings/serializers/terminal.py:24 +msgid "" +"Allow terminal register, after all terminal setup, you should disable this " +"for security" +msgstr "" + +#: settings/serializers/terminal.py:27 +msgid "Password auth" +msgstr "" + +#: settings/serializers/terminal.py:29 +msgid "Public key auth" +msgstr "" + +#: settings/serializers/terminal.py:30 +msgid "" +"Information: If use other auth method, like AD/LDAP, you should disable this " +"to avoid being able to log in after deleting" +msgstr "" + +#: settings/serializers/terminal.py:34 +msgid "Asset list sorting" +msgstr "" + +#: settings/serializers/terminal.py:37 +msgid "Asset list page size" +msgstr "" + +#: settings/tasks/ldap.py:28 +msgid "Periodic import ldap user" +msgstr "" + +#: settings/tasks/ldap.py:66 +msgid "Registration periodic import ldap user task" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:2 +msgid "Sync task Finish" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:6 +#: terminal/models/session/session.py:46 +msgid "Date end" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:9 +msgid "Synced Organization" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:15 +msgid "Synced User" +msgstr "" + +#: settings/templates/ldap/_msg_import_ldap_user.html:22 +msgid "No user synchronization required" +msgstr "" + +#: settings/utils/ldap.py:494 +msgid "ldap:// or ldaps:// protocol is used." +msgstr "" + +#: settings/utils/ldap.py:505 +msgid "Host or port is disconnected: {}" +msgstr "" + +#: settings/utils/ldap.py:507 +msgid "The port is not the port of the LDAP service: {}" +msgstr "" + +#: settings/utils/ldap.py:509 +msgid "Please add certificate: {}" +msgstr "" + +#: settings/utils/ldap.py:513 settings/utils/ldap.py:540 +#: settings/utils/ldap.py:570 settings/utils/ldap.py:598 +msgid "Unknown error: {}" +msgstr "" + +#: settings/utils/ldap.py:527 +msgid "Bind DN or Password incorrect" +msgstr "" + +#: settings/utils/ldap.py:534 +msgid "Please enter Bind DN: {}" +msgstr "" + +#: settings/utils/ldap.py:536 +msgid "Please enter Password: {}" +msgstr "" + +#: settings/utils/ldap.py:538 +msgid "Please enter correct Bind DN and Password: {}" +msgstr "" + +#: settings/utils/ldap.py:556 +msgid "Invalid User OU or User search filter: {}" +msgstr "" + +#: settings/utils/ldap.py:587 +msgid "LDAP User attr map not include: {}" +msgstr "" + +#: settings/utils/ldap.py:594 +msgid "LDAP User attr map is not dict" +msgstr "" + +#: settings/utils/ldap.py:613 +msgid "LDAP authentication is not enabled" +msgstr "" + +#: settings/utils/ldap.py:631 +msgid "Error (Invalid LDAP server): {}" +msgstr "" + +#: settings/utils/ldap.py:633 +msgid "Error (Invalid Bind DN): {}" +msgstr "" + +#: settings/utils/ldap.py:635 +msgid "Error (Invalid LDAP User attr map): {}" +msgstr "" + +#: settings/utils/ldap.py:637 +msgid "Error (Invalid User OU or User search filter): {}" +msgstr "" + +#: settings/utils/ldap.py:639 +msgid "Error (Not enabled LDAP authentication): {}" +msgstr "" + +#: settings/utils/ldap.py:641 +msgid "Error (Unknown): {}" +msgstr "" + +#: settings/utils/ldap.py:644 +msgid "Succeed: Match {} s user" +msgstr "" + +#: settings/utils/ldap.py:677 +msgid "Authentication failed (configuration incorrect): {}" +msgstr "" + +#: settings/utils/ldap.py:681 +msgid "Authentication failed (username or password incorrect): {}" +msgstr "" + +#: settings/utils/ldap.py:683 +msgid "Authentication failed (Unknown): {}" +msgstr "" + +#: settings/utils/ldap.py:686 +msgid "Authentication success: {}" +msgstr "" + +#: settings/ws.py:195 +msgid "Get ldap users is None" +msgstr "" + +#: settings/ws.py:205 +msgid "Imported {} users successfully (Organization: {})" +msgstr "" + +#: templates/_csv_import_export.html:8 +msgid "Export" +msgstr "" + +#: templates/_csv_import_export.html:13 templates/_csv_import_modal.html:5 +msgid "Import" +msgstr "" + +#: templates/_csv_import_modal.html:12 +msgid "Download the imported template or use the exported CSV file format" +msgstr "" + +#: templates/_csv_import_modal.html:13 +msgid "Download the import template" +msgstr "" + +#: templates/_csv_import_modal.html:17 templates/_csv_update_modal.html:17 +msgid "Select the CSV file to import" +msgstr "" + +#: templates/_csv_import_modal.html:39 templates/_csv_update_modal.html:42 +msgid "Please select file" +msgstr "" + +#: templates/_csv_update_modal.html:12 +msgid "Download the update template or use the exported CSV file format" +msgstr "" + +#: templates/_csv_update_modal.html:13 +msgid "Download the update template" +msgstr "" + +#: templates/_header_bar.html:12 +msgid "Help" +msgstr "" + +#: templates/_header_bar.html:19 +msgid "Docs" +msgstr "" + +#: templates/_header_bar.html:27 +msgid "Commercial support" +msgstr "" + +#: templates/_header_bar.html:85 users/forms/profile.py:43 +msgid "Profile" +msgstr "" + +#: templates/_header_bar.html:89 +msgid "Admin page" +msgstr "" + +#: templates/_header_bar.html:92 +msgid "User page" +msgstr "" + +#: templates/_header_bar.html:97 +msgid "Logout" +msgstr "" + +#: templates/_message.html:6 +msgid "" +"\n" +" Your account has expired, please contact the administrator.\n" +" " +msgstr "" + +#: templates/_message.html:13 +msgid "Your account will at" +msgstr "" + +#: templates/_message.html:13 templates/_message.html:30 +msgid "expired. " +msgstr "" + +#: templates/_message.html:23 +#, python-format +msgid "" +"\n" +" Your password has expired, please click this link update password.\n" +" " +msgstr "" + +#: templates/_message.html:30 +msgid "Your password will at" +msgstr "" + +#: templates/_message.html:31 +#, python-format +msgid "" +"\n" +" please click this " +"link to update your password.\n" +" " +msgstr "" + +#: templates/_message.html:43 +#, python-format +msgid "" +"\n" +" Your information was incomplete. Please click this link to complete your information.\n" +" " +msgstr "" + +#: templates/_message.html:56 +#, python-format +msgid "" +"\n" +" Your ssh public key not set or expired. Please click this link to update\n" +" " +msgstr "" + +#: templates/_mfa_login_field.html:28 +msgid "Send verification code" +msgstr "" + +#: templates/_mfa_login_field.html:107 +#: users/templates/users/forgot_password.html:176 +msgid "Wait: " +msgstr "" + +#: templates/_mfa_login_field.html:117 +#: users/templates/users/forgot_password.html:192 +msgid "The verification code has been sent" +msgstr "" + +#: templates/_without_nav_base.html:26 +msgid "Home page" +msgstr "" + +#: templates/resource_download.html:18 templates/resource_download.html:33 +#: users/const.py:65 +msgid "Client" +msgstr "" + +#: templates/resource_download.html:20 +msgid "" +"JumpServer Client, currently used to launch the client, now only support " +"launch RDP SSH client, The Telnet client will next" +msgstr "" + +#: templates/resource_download.html:33 +msgid "Microsoft" +msgstr "" + +#: templates/resource_download.html:33 +msgid "Official" +msgstr "" + +#: templates/resource_download.html:35 +msgid "" +"macOS needs to download the client to connect RDP asset, which comes with " +"Windows" +msgstr "" + +#: templates/resource_download.html:44 +msgid "Windows Remote application publisher tools" +msgstr "" + +#: templates/resource_download.html:45 +msgid "" +"OpenSSH is a program used to connect remote applications in the Windows " +"Remote Application Publisher" +msgstr "" + +#: templates/resource_download.html:53 +msgid "Offline video player" +msgstr "" + +#: terminal/api/applet/applet.py:52 terminal/api/applet/applet.py:55 +#: terminal/api/virtualapp/virtualapp.py:43 +#: terminal/api/virtualapp/virtualapp.py:46 +msgid "Invalid zip file" +msgstr "" + +#: terminal/api/applet/applet.py:74 +msgid "This is enterprise edition applet" +msgstr "" + +#: terminal/api/component/endpoint.py:32 +msgid "Not found protocol query params" +msgstr "" + +#: terminal/api/component/storage.py:31 +msgid "Deleting the default storage is not allowed" +msgstr "" + +#: terminal/api/component/storage.py:34 +msgid "Cannot delete storage that is being used" +msgstr "" + +#: terminal/api/component/storage.py:75 terminal/api/component/storage.py:76 +msgid "Command storages" +msgstr "" + +#: terminal/api/component/storage.py:82 +msgid "Invalid" +msgstr "" + +#: terminal/api/component/storage.py:130 terminal/tasks.py:149 +msgid "Test failure: {}" +msgstr "" + +#: terminal/api/component/storage.py:133 +msgid "Test successful" +msgstr "" + +#: terminal/api/component/storage.py:135 +msgid "Test failure: Please check configuration" +msgstr "" + +#: terminal/api/component/terminal.py:55 +msgid "Have online sessions" +msgstr "" + +#: terminal/api/session/session.py:48 +#, python-format +msgid "User %s %s session %s replay" +msgstr "" + +#: terminal/api/session/session.py:317 +msgid "Session does not exist: {}" +msgstr "" + +#: terminal/api/session/session.py:320 +msgid "Session is finished or the protocol not supported" +msgstr "" + +#: terminal/api/session/session.py:333 +msgid "User does not have permission" +msgstr "" + +#: terminal/api/session/sharing.py:29 +msgid "Secure session sharing settings is disabled" +msgstr "" + +#: terminal/apps.py:9 +msgid "App Terminals" +msgstr "" + +#: terminal/backends/command/models.py:19 +msgid "Input" +msgstr "" + +#: terminal/backends/command/models.py:20 terminal/serializers/command.py:73 +msgid "Output" +msgstr "" + +#: terminal/backends/command/models.py:24 terminal/serializers/command.py:22 +#: terminal/templates/terminal/_msg_command_warning.html:10 +msgid "Risk level" +msgstr "" + +#: terminal/connect_methods.py:29 +msgid "SSH Client" +msgstr "" + +#: terminal/connect_methods.py:30 +msgid "SSH Guide" +msgstr "" + +#: terminal/connect_methods.py:31 +msgid "SFTP Client" +msgstr "" + +#: terminal/connect_methods.py:33 +msgid "DB Guide" +msgstr "" + +#: terminal/connect_methods.py:34 +msgid "DB Client" +msgstr "" + +#: terminal/connect_methods.py:36 +msgid "Remote Desktop" +msgstr "" + +#: terminal/connect_methods.py:37 +msgid "RDP Guide" +msgstr "" + +#: terminal/const.py:10 +msgid "Warning" +msgstr "" + +#: terminal/const.py:12 +msgid "Review & Reject" +msgstr "" + +#: terminal/const.py:13 +msgid "Review & Accept" +msgstr "" + +#: terminal/const.py:14 +msgid "Review & Cancel" +msgstr "" + +#: terminal/const.py:45 +msgid "Critical" +msgstr "" + +#: terminal/const.py:46 +msgid "High" +msgstr "" + +#: terminal/const.py:47 terminal/const.py:84 +#: users/templates/users/reset_password.html:50 +msgid "Normal" +msgstr "" + +#: terminal/const.py:48 +msgid "Offline" +msgstr "" + +#: terminal/const.py:80 +msgid "Mismatch" +msgstr "" + +#: terminal/const.py:85 +msgid "Tunnel" +msgstr "" + +#: terminal/const.py:91 +msgid "Read only" +msgstr "" + +#: terminal/const.py:92 +msgid "Writable" +msgstr "" + +#: terminal/const.py:96 +msgid "Kill session" +msgstr "" + +#: terminal/const.py:97 +msgid "Lock session" +msgstr "" + +#: terminal/const.py:98 +msgid "Unlock session" +msgstr "" + +#: terminal/const.py:103 +msgid "Replay create failed" +msgstr "" + +#: terminal/const.py:104 +msgid "Replay upload failed" +msgstr "" + +#: terminal/const.py:105 +msgid "Replay convert failed" +msgstr "" + +#: terminal/const.py:106 +msgid "Replay unsupported" +msgstr "" + +#: terminal/exceptions.py:8 +msgid "Bulk create not support" +msgstr "" + +#: terminal/exceptions.py:13 +msgid "Storage is invalid" +msgstr "" + +#: terminal/models/applet/applet.py:30 xpack/plugins/license/models.py:88 +msgid "Community edition" +msgstr "" + +#: terminal/models/applet/applet.py:31 +msgid "Enterprise" +msgstr "" + +#: terminal/models/applet/applet.py:36 +#: terminal/models/virtualapp/virtualapp.py:22 +msgid "Author" +msgstr "" + +#: terminal/models/applet/applet.py:38 terminal/serializers/applet.py:31 +msgid "Edition" +msgstr "" + +#: terminal/models/applet/applet.py:43 +msgid "Can concurrent" +msgstr "" + +#: terminal/models/applet/applet.py:44 +#: terminal/models/virtualapp/virtualapp.py:29 +msgid "Tags" +msgstr "" + +#: terminal/models/applet/applet.py:48 terminal/serializers/applet_host.py:167 +#: terminal/serializers/storage.py:197 +msgid "Hosts" +msgstr "" + +#: terminal/models/applet/applet.py:93 +#: terminal/models/virtualapp/virtualapp.py:66 +msgid "Applet pkg not valid, Missing file {}" +msgstr "" + +#: terminal/models/applet/applet.py:112 +msgid "Load platform.yml failed: {}" +msgstr "" + +#: terminal/models/applet/applet.py:115 +msgid "Only support custom platform" +msgstr "" + +#: terminal/models/applet/applet.py:120 +msgid "Missing type in platform.yml" +msgstr "" + +#: terminal/models/applet/applet.py:319 terminal/models/applet/host.py:36 +#: terminal/models/applet/host.py:138 +msgid "Hosting" +msgstr "" + +#: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:69 +msgid "Deploy options" +msgstr "" + +#: terminal/models/applet/host.py:19 +msgid "Auto create accounts" +msgstr "" + +#: terminal/models/applet/host.py:20 +msgid "Accounts create amount" +msgstr "" + +#: terminal/models/applet/host.py:21 +msgid "Inited" +msgstr "" + +#: terminal/models/applet/host.py:22 +msgid "Date inited" +msgstr "" + +#: terminal/models/applet/host.py:23 +msgid "Date synced" +msgstr "" + +#: terminal/models/applet/host.py:28 +msgid "Using same account" +msgstr "" + +#: terminal/models/applet/host.py:139 +msgid "Initial" +msgstr "" + +#: terminal/models/component/endpoint.py:15 +msgid "HTTPS port" +msgstr "" + +#: terminal/models/component/endpoint.py:16 +msgid "HTTP port" +msgstr "" + +#: terminal/models/component/endpoint.py:17 +msgid "SSH port" +msgstr "" + +#: terminal/models/component/endpoint.py:18 +msgid "RDP port" +msgstr "" + +#: terminal/models/component/endpoint.py:19 +msgid "MySQL port" +msgstr "" + +#: terminal/models/component/endpoint.py:20 +msgid "MariaDB port" +msgstr "" + +#: terminal/models/component/endpoint.py:21 +msgid "PostgreSQL port" +msgstr "" + +#: terminal/models/component/endpoint.py:22 +msgid "Redis port" +msgstr "" + +#: terminal/models/component/endpoint.py:23 +msgid "SQLServer port" +msgstr "" + +#: terminal/models/component/endpoint.py:30 +#: terminal/models/component/endpoint.py:117 +#: terminal/serializers/endpoint.py:73 terminal/serializers/storage.py:41 +#: terminal/serializers/storage.py:53 terminal/serializers/storage.py:83 +#: terminal/serializers/storage.py:93 terminal/serializers/storage.py:101 +msgid "Endpoint" +msgstr "" + +#: terminal/models/component/endpoint.py:123 +msgid "Endpoint rule" +msgstr "" + +#: terminal/models/component/status.py:15 +msgid "Session Online" +msgstr "" + +#: terminal/models/component/status.py:16 +msgid "CPU Load" +msgstr "" + +#: terminal/models/component/status.py:17 +msgid "Memory Used" +msgstr "" + +#: terminal/models/component/status.py:18 +msgid "Disk Used" +msgstr "" + +#: terminal/models/component/status.py:19 +msgid "Connections" +msgstr "" + +#: terminal/models/component/status.py:20 +msgid "Threads" +msgstr "" + +#: terminal/models/component/status.py:21 +msgid "Boot Time" +msgstr "" + +#: terminal/models/component/storage.py:28 +msgid "Default storage" +msgstr "" + +#: terminal/models/component/storage.py:140 +#: terminal/models/component/terminal.py:91 +msgid "Command storage" +msgstr "" + +#: terminal/models/component/storage.py:204 +#: terminal/models/component/terminal.py:92 +msgid "Replay storage" +msgstr "" + +#: terminal/models/component/terminal.py:88 +msgid "type" +msgstr "" + +#: terminal/models/component/terminal.py:90 terminal/serializers/command.py:76 +msgid "Remote Address" +msgstr "" + +#: terminal/models/component/terminal.py:93 +msgid "Application User" +msgstr "" + +#: terminal/models/component/terminal.py:177 +msgid "Can view terminal config" +msgstr "" + +#: terminal/models/session/command.py:76 +msgid "Command record" +msgstr "" + +#: terminal/models/session/replay.py:12 +msgid "Session replay" +msgstr "" + +#: terminal/models/session/replay.py:14 +msgid "Can upload session replay" +msgstr "" + +#: terminal/models/session/replay.py:15 +msgid "Can download session replay" +msgstr "" + +#: terminal/models/session/session.py:35 +msgid "Account ID" +msgstr "" + +#: terminal/models/session/session.py:37 terminal/models/session/sharing.py:118 +msgid "Login from" +msgstr "" + +#: terminal/models/session/session.py:42 +msgid "Replay" +msgstr "" + +#: terminal/models/session/session.py:48 terminal/serializers/session.py:68 +msgid "Command amount" +msgstr "" + +#: terminal/models/session/session.py:49 terminal/serializers/session.py:30 +msgid "Error reason" +msgstr "" + +#: terminal/models/session/session.py:290 +msgid "Session record" +msgstr "" + +#: terminal/models/session/session.py:292 +msgid "Can monitor session" +msgstr "" + +#: terminal/models/session/session.py:293 +msgid "Can share session" +msgstr "" + +#: terminal/models/session/session.py:294 +msgid "Can terminate session" +msgstr "" + +#: terminal/models/session/session.py:295 +msgid "Can validate session action perm" +msgstr "" + +#: terminal/models/session/sharing.py:32 +msgid "Expired time (min)" +msgstr "" + +#: terminal/models/session/sharing.py:36 terminal/serializers/sharing.py:20 +#: terminal/serializers/sharing.py:52 +msgid "Action permission" +msgstr "" + +#: terminal/models/session/sharing.py:38 +msgid "Origin" +msgstr "" + +#: terminal/models/session/sharing.py:42 terminal/models/session/sharing.py:100 +#: terminal/notifications.py:261 +msgid "Session sharing" +msgstr "" + +#: terminal/models/session/sharing.py:44 +msgid "Can add super session sharing" +msgstr "" + +#: terminal/models/session/sharing.py:83 +msgid "Link not active" +msgstr "" + +#: terminal/models/session/sharing.py:85 +msgid "Link expired" +msgstr "" + +#: terminal/models/session/sharing.py:87 +msgid "User not allowed to join" +msgstr "" + +#: terminal/models/session/sharing.py:104 terminal/serializers/sharing.py:71 +msgid "Joiner" +msgstr "" + +#: terminal/models/session/sharing.py:107 +msgid "Date joined" +msgstr "" + +#: terminal/models/session/sharing.py:110 +msgid "Date left" +msgstr "" + +#: terminal/models/session/sharing.py:133 +msgid "Session join record" +msgstr "" + +#: terminal/models/session/sharing.py:149 +msgid "Invalid verification code" +msgstr "" + +#: terminal/models/session/sharing.py:156 +msgid "You have already joined this session" +msgstr "" + +#: terminal/models/virtualapp/provider.py:11 +msgid "Hostname" +msgstr "" + +#: terminal/models/virtualapp/virtualapp.py:32 +msgid "Providers" +msgstr "" + +#: terminal/models/virtualapp/virtualapp.py:94 +#: terminal/serializers/virtualapp.py:34 +msgid "App Provider" +msgstr "" + +#: terminal/models/virtualapp/virtualapp.py:102 +msgid "Virtual app publication" +msgstr "" + +#: terminal/notifications.py:25 +msgid "Sessions" +msgstr "" + +#: terminal/notifications.py:72 +msgid "Command warning" +msgstr "" + +#: terminal/notifications.py:130 terminal/notifications.py:175 +msgid "Command reject" +msgstr "" + +#: terminal/notifications.py:157 terminal/notifications.py:206 +msgid "Level" +msgstr "" + +#: terminal/notifications.py:224 +msgid "Command and replay storage" +msgstr "" + +#: terminal/notifications.py:240 terminal/tasks.py:153 +msgid "Test failure: Account invalid" +msgstr "" + +#: terminal/notifications.py:250 +#: terminal/templates/terminal/_msg_check_command_replay_storage_connectivity.html:4 +msgid "Invalid storage" +msgstr "" + +#: terminal/serializers/applet.py:28 terminal/serializers/virtualapp.py:15 +msgid "Icon" +msgstr "" + +#: terminal/serializers/applet_host.py:24 +msgid "Per Session" +msgstr "" + +#: terminal/serializers/applet_host.py:25 +msgid "Per Device" +msgstr "" + +#: terminal/serializers/applet_host.py:37 +msgid "Core API" +msgstr "" + +#: terminal/serializers/applet_host.py:38 +msgid "" +" \n" +" Tips: The application release machine communicates with the Core " +"service. \n" +" If the release machine and the Core service are on the same network " +"segment, \n" +" it is recommended to fill in the intranet address, otherwise fill in " +"the current site URL \n" +"
\n" +" eg: https://172.16.10.110 or https://dev.jumpserver.com\n" +" " +msgstr "" + +#: terminal/serializers/applet_host.py:46 terminal/serializers/storage.py:208 +msgid "Ignore Certificate Verification" +msgstr "" + +#: terminal/serializers/applet_host.py:47 +msgid "Existing RDS license" +msgstr "" + +#: terminal/serializers/applet_host.py:48 +msgid "RDS License Server" +msgstr "" + +#: terminal/serializers/applet_host.py:49 +msgid "RDS Licensing Mode" +msgstr "" + +#: terminal/serializers/applet_host.py:51 +msgid "RDS Single Session Per User" +msgstr "" + +#: terminal/serializers/applet_host.py:53 +msgid "RDS Max Disconnection Time (ms)" +msgstr "" + +#: terminal/serializers/applet_host.py:55 +msgid "" +"Tips: Set the maximum duration for keeping a disconnected session active on " +"the server (log off the session after 60000 milliseconds)." +msgstr "" + +#: terminal/serializers/applet_host.py:60 +msgid "RDS Remote App Logoff Time Limit (ms)" +msgstr "" + +#: terminal/serializers/applet_host.py:62 +msgid "" +"Tips: Set the logoff time for RemoteApp sessions after closing all RemoteApp " +"programs (0 milliseconds, log off the session immediately)." +msgstr "" + +#: terminal/serializers/applet_host.py:71 terminal/serializers/terminal.py:47 +#: terminal/serializers/virtualapp_provider.py:13 +msgid "Load status" +msgstr "" + +#: terminal/serializers/applet_host.py:85 +msgid "" +"These accounts are used to connect to the published application, the account " +"is now divided into two types, one is dedicated to each account, each user " +"has a private account, the other is public, when the application does not " +"support multiple open and the special has been used, the public account will " +"be used to connect" +msgstr "" + +#: terminal/serializers/applet_host.py:92 +msgid "The number of public accounts created automatically" +msgstr "" + +#: terminal/serializers/applet_host.py:95 +msgid "" +"Connect to the host using the same account first. For security reasons, " +"please set the configuration item CACHE_LOGIN_PASSWORD_ENABLED=true and " +"restart the service to enable it." +msgstr "" + +#: terminal/serializers/applet_host.py:137 +msgid "Install applets" +msgstr "" + +#: terminal/serializers/applet_host.py:167 +msgid "Host ID" +msgstr "" + +#: terminal/serializers/applet_host.py:168 +msgid "Applet ID" +msgstr "" + +#: terminal/serializers/command.py:19 +msgid "Session ID" +msgstr "" + +#: terminal/serializers/command.py:41 +msgid "Command Filter ACL" +msgstr "" + +#: terminal/serializers/command.py:44 +msgid "Command Group" +msgstr "" + +#: terminal/serializers/command.py:55 +msgid "Invalid command filter ACL id" +msgstr "" + +#: terminal/serializers/command.py:59 +msgid "Invalid command group id" +msgstr "" + +#: terminal/serializers/command.py:63 +msgid "Invalid session id" +msgstr "" + +#: terminal/serializers/command.py:74 +msgid "Timestamp" +msgstr "" + +#: terminal/serializers/endpoint.py:15 +msgid "Oracle port" +msgstr "" + +#: terminal/serializers/endpoint.py:18 +msgid "Oracle port range" +msgstr "" + +#: terminal/serializers/endpoint.py:20 +msgid "" +"Oracle proxy server listen port is dynamic, Each additional Oracle database " +"instance adds a port listener" +msgstr "" + +#: terminal/serializers/endpoint.py:38 +msgid "" +"The host address accessed when connecting to assets, if it is empty, the " +"access address of the current browser will be used (the default endpoint " +"does not allow modification of the host)" +msgstr "" + +#: terminal/serializers/endpoint.py:64 +msgid "" +"The assets within this IP range, the following endpoint will be used for the " +"connection" +msgstr "" + +#: terminal/serializers/endpoint.py:65 +msgid "" +"If asset IP addresses under different endpoints conflict, use asset labels" +msgstr "" + +#: terminal/serializers/endpoint.py:69 +msgid "Asset IP" +msgstr "" + +#: terminal/serializers/session.py:25 terminal/serializers/session.py:53 +msgid "Can replay" +msgstr "" + +#: terminal/serializers/session.py:26 terminal/serializers/session.py:54 +msgid "Can join" +msgstr "" + +#: terminal/serializers/session.py:27 terminal/serializers/session.py:57 +msgid "Can terminate" +msgstr "" + +#: terminal/serializers/session.py:47 +msgid "Duration" +msgstr "" + +#: terminal/serializers/session.py:49 +msgid "User ID" +msgstr "" + +#: terminal/serializers/session.py:50 +msgid "Asset ID" +msgstr "" + +#: terminal/serializers/session.py:51 +msgid "Login from display" +msgstr "" + +#: terminal/serializers/session.py:58 +msgid "Terminal display" +msgstr "" + +#: terminal/serializers/storage.py:23 +msgid "Endpoint invalid: remove path `{}`" +msgstr "" + +#: terminal/serializers/storage.py:29 +msgid "Bucket" +msgstr "" + +#: terminal/serializers/storage.py:33 +msgid "Access key ID" +msgstr "" + +#: terminal/serializers/storage.py:37 +#: xpack/plugins/cloud/serializers/account_attrs.py:20 +msgid "Access key secret" +msgstr "" + +#: terminal/serializers/storage.py:68 xpack/plugins/cloud/models.py:253 +msgid "Region" +msgstr "" + +#: terminal/serializers/storage.py:112 +msgid "Container name" +msgstr "" + +#: terminal/serializers/storage.py:115 +msgid "Account key" +msgstr "" + +#: terminal/serializers/storage.py:118 +msgid "Endpoint suffix" +msgstr "" + +#: terminal/serializers/storage.py:129 +msgid "HOST" +msgstr "" + +#: terminal/serializers/storage.py:146 users/models/user.py:904 +#: xpack/plugins/cloud/serializers/account_attrs.py:213 +msgid "Private key" +msgstr "" + +#: terminal/serializers/storage.py:152 +msgid "SFTP Root" +msgstr "" + +#: terminal/serializers/storage.py:173 +msgid "The address cannot contain the special character `#`" +msgstr "" + +#: terminal/serializers/storage.py:175 +msgid "The address format is incorrect" +msgstr "" + +#: terminal/serializers/storage.py:182 +msgid "Host invalid" +msgstr "" + +#: terminal/serializers/storage.py:185 +msgid "Port invalid" +msgstr "" + +#: terminal/serializers/storage.py:200 +msgid "Index by date" +msgstr "" + +#: terminal/serializers/storage.py:201 +msgid "Whether to create an index by date" +msgstr "" + +#: terminal/serializers/storage.py:204 +msgid "Index" +msgstr "" + +#: terminal/serializers/storage.py:206 +msgid "Doc type" +msgstr "" + +#: terminal/serializers/task.py:9 +msgid "Session id" +msgstr "" + +#: terminal/serializers/terminal.py:42 +msgid "Online sessions" +msgstr "" + +#: terminal/serializers/terminal.py:43 +msgid "Is alive" +msgstr "" + +#: terminal/serializers/terminal.py:49 +msgid "Stat" +msgstr "" + +#: terminal/serializers/terminal.py:83 terminal/serializers/terminal.py:91 +msgid "Not found" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:26 +msgid "Container ID" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:27 +msgid "Container Image" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:28 +msgid "Container Name" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:29 +msgid "Container Status" +msgstr "" + +#: terminal/serializers/virtualapp_provider.py:30 +msgid "Container Ports" +msgstr "" + +#: terminal/session_lifecycle.py:30 +#, python-format +msgid "Connect to asset %s success" +msgstr "" + +#: terminal/session_lifecycle.py:38 +#, python-format +msgid "Connect to asset %s finished: %s" +msgstr "" + +#: terminal/session_lifecycle.py:48 +#, python-format +msgid "User %s create share link" +msgstr "" + +#: terminal/session_lifecycle.py:57 +#, python-format +msgid "User %s join session" +msgstr "" + +#: terminal/session_lifecycle.py:69 +#, python-format +msgid "User %s leave session" +msgstr "" + +#: terminal/session_lifecycle.py:81 +#, python-format +msgid "User %s join to monitor session" +msgstr "" + +#: terminal/session_lifecycle.py:93 +#, python-format +msgid "User %s exit to monitor session" +msgstr "" + +#: terminal/session_lifecycle.py:105 +msgid "Replay start to convert" +msgstr "" + +#: terminal/session_lifecycle.py:113 +msgid "Replay successfully converted to MP4 format" +msgstr "" + +#: terminal/session_lifecycle.py:121 +#, python-format +msgid "Replay failed to convert to MP4 format: %s" +msgstr "" + +#: terminal/session_lifecycle.py:129 +msgid "Replay start to upload" +msgstr "" + +#: terminal/session_lifecycle.py:137 +msgid "Replay successfully uploaded" +msgstr "" + +#: terminal/session_lifecycle.py:145 +#, python-format +msgid "Replay failed to upload: %s" +msgstr "" + +#: terminal/session_lifecycle.py:152 +msgid "connect failed" +msgstr "" + +#: terminal/session_lifecycle.py:153 +msgid "connection disconnect" +msgstr "" + +#: terminal/session_lifecycle.py:154 +msgid "user closed" +msgstr "" + +#: terminal/session_lifecycle.py:155 +msgid "idle disconnect" +msgstr "" + +#: terminal/session_lifecycle.py:156 +msgid "admin terminated" +msgstr "" + +#: terminal/session_lifecycle.py:157 +msgid "maximum session time has been reached" +msgstr "" + +#: terminal/session_lifecycle.py:158 +msgid "permission has expired" +msgstr "" + +#: terminal/session_lifecycle.py:159 +msgid "storage is null" +msgstr "" + +#: terminal/tasks.py:31 +msgid "Periodic delete terminal status" +msgstr "" + +#: terminal/tasks.py:39 +msgid "Clean orphan session" +msgstr "" + +#: terminal/tasks.py:87 +msgid "Run applet host deployment" +msgstr "" + +#: terminal/tasks.py:97 +msgid "Install applet" +msgstr "" + +#: terminal/tasks.py:108 +msgid "Uninstall applet" +msgstr "" + +#: terminal/tasks.py:119 +msgid "Generate applet host accounts" +msgstr "" + +#: terminal/tasks.py:131 +msgid "Check command replay storage connectivity" +msgstr "" + +#: terminal/templates/terminal/_msg_command_alert.html:10 +msgid "view" +msgstr "" + +#: terminal/utils/db_port_mapper.py:85 +msgid "" +"No available port is matched. The number of databases may have exceeded the " +"number of ports open to the database agent service, Contact the " +"administrator to open more ports." +msgstr "" + +#: terminal/utils/db_port_mapper.py:113 +msgid "" +"No ports can be used, check and modify the limit on the number of ports that " +"Magnus listens on in the configuration file." +msgstr "" + +#: terminal/utils/db_port_mapper.py:115 +msgid "All available port count: {}, Already use port count: {}" +msgstr "" + +#: tickets/api/ticket.py:88 tickets/models/ticket/general.py:286 +msgid "Applicant" +msgstr "" + +#: tickets/apps.py:7 +msgid "App Tickets" +msgstr "" + +#: tickets/const.py:10 +msgid "Apply for asset" +msgstr "" + +#: tickets/const.py:17 tickets/const.py:24 tickets/const.py:42 +msgid "Open" +msgstr "" + +#: tickets/const.py:19 tickets/const.py:31 +msgid "Approved" +msgstr "" + +#: tickets/const.py:20 tickets/const.py:32 +msgid "Rejected" +msgstr "" + +#: tickets/const.py:30 tickets/const.py:37 +msgid "Closed" +msgstr "" + +#: tickets/const.py:49 +msgid "One level" +msgstr "" + +#: tickets/const.py:50 +msgid "Two level" +msgstr "" + +#: tickets/const.py:54 +msgid "Org admin" +msgstr "" + +#: tickets/const.py:55 +msgid "Custom user" +msgstr "" + +#: tickets/const.py:56 +msgid "Super admin" +msgstr "" + +#: tickets/const.py:57 +msgid "Super admin and org admin" +msgstr "" + +#: tickets/const.py:61 +msgid "All assets" +msgstr "" + +#: tickets/const.py:62 +msgid "Permed assets" +msgstr "" + +#: tickets/const.py:63 +msgid "Permed valid assets" +msgstr "" + +#: tickets/errors.py:9 +msgid "Ticket already closed" +msgstr "" + +#: tickets/handlers/apply_asset.py:36 +msgid "" +"Created by the ticket ticket title: {} ticket applicant: {} ticket " +"processor: {} ticket ID: {}" +msgstr "" + +#: tickets/handlers/base.py:85 +msgid "Change field" +msgstr "" + +#: tickets/handlers/base.py:85 +msgid "Before change" +msgstr "" + +#: tickets/handlers/base.py:85 +msgid "After change" +msgstr "" + +#: tickets/handlers/base.py:97 +msgid "{} {} the ticket" +msgstr "" + +#: tickets/models/comment.py:14 +msgid "common" +msgstr "" + +#: tickets/models/comment.py:23 +msgid "User display name" +msgstr "" + +#: tickets/models/comment.py:24 +msgid "Body" +msgstr "" + +#: tickets/models/flow.py:19 tickets/models/flow.py:61 +#: tickets/models/ticket/general.py:42 +msgid "Approve level" +msgstr "" + +#: tickets/models/flow.py:24 tickets/serializers/flow.py:17 +msgid "Approve strategy" +msgstr "" + +#: tickets/models/flow.py:29 tickets/serializers/flow.py:19 +msgid "Assignees" +msgstr "" + +#: tickets/models/flow.py:33 +msgid "Ticket flow approval rule" +msgstr "" + +#: tickets/models/flow.py:66 +msgid "Ticket flow" +msgstr "" + +#: tickets/models/relation.py:12 +msgid "Ticket session relation" +msgstr "" + +#: tickets/models/ticket/apply_application.py:10 +#: tickets/models/ticket/apply_asset.py:13 +msgid "Permission name" +msgstr "" + +#: tickets/models/ticket/apply_application.py:19 +msgid "Apply applications" +msgstr "" + +#: tickets/models/ticket/apply_application.py:22 +msgid "Apply system users" +msgstr "" + +#: tickets/models/ticket/apply_asset.py:9 +#: tickets/serializers/ticket/apply_asset.py:14 +msgid "Select at least one asset or node" +msgstr "" + +#: tickets/models/ticket/apply_asset.py:17 +msgid "Apply accounts" +msgstr "" + +#: tickets/models/ticket/apply_asset.py:26 +msgid "Apply Asset Ticket" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:9 +msgid "Run user" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:11 +msgid "Run asset" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:12 +msgid "Run command" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:19 +msgid "Command filter acl" +msgstr "" + +#: tickets/models/ticket/command_confirm.py:23 +msgid "Apply Command Ticket" +msgstr "" + +#: tickets/models/ticket/general.py:77 +msgid "Ticket step" +msgstr "" + +#: tickets/models/ticket/general.py:95 +msgid "Ticket assignee" +msgstr "" + +#: tickets/models/ticket/general.py:270 +msgid "Title" +msgstr "" + +#: tickets/models/ticket/general.py:290 +msgid "TicketFlow" +msgstr "" + +#: tickets/models/ticket/general.py:293 +msgid "Approval step" +msgstr "" + +#: tickets/models/ticket/general.py:296 +msgid "Relation snapshot" +msgstr "" + +#: tickets/models/ticket/general.py:399 +msgid "Please try again" +msgstr "" + +#: tickets/models/ticket/general.py:475 +msgid "Super ticket" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:11 +msgid "Login user" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:14 +msgid "Login asset" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:17 +msgid "Login account" +msgstr "" + +#: tickets/models/ticket/login_asset_confirm.py:27 +msgid "Apply Login Asset Ticket" +msgstr "" + +#: tickets/models/ticket/login_confirm.py:15 +msgid "Apply Login Ticket" +msgstr "" + +#: tickets/notifications.py:63 +msgid "Ticket basic info" +msgstr "" + +#: tickets/notifications.py:64 +msgid "Ticket applied info" +msgstr "" + +#: tickets/notifications.py:105 +msgid "Your has a new ticket, applicant - {}" +msgstr "" + +#: tickets/notifications.py:109 +msgid "{}: New Ticket - {} ({})" +msgstr "" + +#: tickets/notifications.py:155 +msgid "Your ticket has been processed, processor - {}" +msgstr "" + +#: tickets/notifications.py:159 +msgid "Ticket has processed - {} ({})" +msgstr "" + +#: tickets/serializers/flow.py:20 +msgid "Assignees display" +msgstr "" + +#: tickets/serializers/flow.py:46 +msgid "Please select the Assignees" +msgstr "" + +#: tickets/serializers/flow.py:74 +msgid "The current organization type already exists" +msgstr "" + +#: tickets/serializers/super_ticket.py:15 +msgid "Processor" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:16 +msgid "Support fuzzy search, and display up to 10 items" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:22 +msgid "Apply assets" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:26 +msgid "Apply nodes" +msgstr "" + +#: tickets/serializers/ticket/apply_asset.py:28 +msgid "Apply actions" +msgstr "" + +#: tickets/serializers/ticket/common.py:15 +#: tickets/serializers/ticket/common.py:75 +msgid "Created by ticket ({}-{})" +msgstr "" + +#: tickets/serializers/ticket/common.py:67 +msgid "The expiration date should be greater than the start date" +msgstr "" + +#: tickets/serializers/ticket/common.py:82 +msgid "Permission named `{}` already exists" +msgstr "" + +#: tickets/serializers/ticket/ticket.py:89 +msgid "The ticket flow `{}` does not exist" +msgstr "" + +#: tickets/templates/tickets/_msg_ticket.html:21 +msgid "View details" +msgstr "" + +#: tickets/templates/tickets/_msg_ticket.html:26 +msgid "Direct approval" +msgstr "" + +#: tickets/templates/tickets/approve_check_password.html:11 +msgid "Ticket information" +msgstr "" + +#: tickets/templates/tickets/approve_check_password.html:28 +#: tickets/views/approve.py:43 tickets/views/approve.py:80 +msgid "Ticket approval" +msgstr "" + +#: tickets/templates/tickets/approve_check_password.html:43 +msgid "Approval" +msgstr "" + +#: tickets/views/approve.py:44 +msgid "" +"This ticket does not exist, the process has ended, or this link has expired" +msgstr "" + +#: tickets/views/approve.py:72 +msgid "Click the button below to approve or reject" +msgstr "" + +#: tickets/views/approve.py:81 +msgid "After successful authentication, this ticket can be approved directly" +msgstr "" + +#: tickets/views/approve.py:105 +msgid "Illegal approval action" +msgstr "" + +#: tickets/views/approve.py:119 +msgid "This user is not authorized to approve this ticket" +msgstr "" + +#: users/api/user.py:155 +msgid "Can not invite self" +msgstr "" + +#: users/api/user.py:208 +msgid "Could not reset self otp, use profile reset instead" +msgstr "" + +#: users/apps.py:9 +msgid "App Users" +msgstr "" + +#: users/const.py:10 +msgid "System administrator" +msgstr "" + +#: users/const.py:11 +msgid "System auditor" +msgstr "" + +#: users/const.py:12 +msgid "Organization administrator" +msgstr "" + +#: users/const.py:13 +msgid "Organization auditor" +msgstr "" + +#: users/const.py:18 +msgid "Reset link will be generated and sent to the user" +msgstr "" + +#: users/const.py:19 +msgid "Set password" +msgstr "" + +#: users/const.py:23 +msgid "AUTO" +msgstr "" + +#: users/const.py:31 +msgid "Full screen" +msgstr "" + +#: users/const.py:32 +msgid "Multi screen" +msgstr "" + +#: users/const.py:33 +msgid "Drives redirect" +msgstr "" + +#: users/const.py:37 +msgid "Current window" +msgstr "" + +#: users/const.py:38 +msgid "New window" +msgstr "" + +#: users/const.py:47 +msgid "High(32 bit)" +msgstr "" + +#: users/const.py:48 +msgid "Medium(16 bit)" +msgstr "" + +#: users/const.py:69 +msgid "Replace" +msgstr "" + +#: users/const.py:70 +msgid "Suffix" +msgstr "" + +#: users/exceptions.py:10 +msgid "MFA not enabled" +msgstr "" + +#: users/exceptions.py:20 +msgid "Unable to delete all users" +msgstr "" + +#: users/forms/profile.py:48 +msgid "" +"When enabled, you will enter the MFA binding process the next time you log " +"in. you can also directly bind in \"personal information -> quick " +"modification -> change MFA Settings\"!" +msgstr "" + +#: users/forms/profile.py:59 +msgid "* Enable MFA to make the account more secure." +msgstr "" + +#: users/forms/profile.py:68 +msgid "" +"In order to protect you and your company, please keep your account, password " +"and key sensitive information properly. (for example: setting complex " +"password, enabling MFA)" +msgstr "" + +#: users/forms/profile.py:75 +msgid "Finish" +msgstr "" + +#: users/forms/profile.py:82 +msgid "New password" +msgstr "" + +#: users/forms/profile.py:87 +msgid "Confirm password" +msgstr "" + +#: users/forms/profile.py:95 +msgid "Password does not match" +msgstr "" + +#: users/forms/profile.py:104 +msgid "The phone number must contain an area code, for example, +86" +msgstr "" + +#: users/forms/profile.py:120 +msgid "Old password" +msgstr "" + +#: users/forms/profile.py:130 +msgid "Old password error" +msgstr "" + +#: users/forms/profile.py:140 +msgid "Automatically configure and download the SSH key" +msgstr "" + +#: users/forms/profile.py:142 +msgid "ssh public key" +msgstr "" + +#: users/forms/profile.py:143 +msgid "ssh-rsa AAAA..." +msgstr "" + +#: users/forms/profile.py:144 +msgid "Paste your id_rsa.pub here." +msgstr "" + +#: users/forms/profile.py:157 +msgid "Public key should not be the same as your old one." +msgstr "" + +#: users/forms/profile.py:161 users/serializers/profile.py:76 +#: users/serializers/profile.py:165 users/serializers/profile.py:192 +msgid "Not a valid ssh public key" +msgstr "" + +#: users/forms/profile.py:172 users/models/user.py:907 +#: xpack/plugins/cloud/serializers/account_attrs.py:210 +msgid "Public key" +msgstr "" + +#: users/models/preference.py:38 users/serializers/preference/preference.py:19 +msgid "Preference" +msgstr "" + +#: users/models/user.py:656 users/serializers/profile.py:94 +msgid "Force enable" +msgstr "" + +#: users/models/user.py:761 +msgid "Lark" +msgstr "" + +#: users/models/user.py:886 users/serializers/user.py:182 +msgid "Is service account" +msgstr "" + +#: users/models/user.py:888 +msgid "Avatar" +msgstr "" + +#: users/models/user.py:891 +msgid "Wechat" +msgstr "" + +#: users/models/user.py:894 users/serializers/user.py:112 +msgid "Phone" +msgstr "" + +#: users/models/user.py:900 +msgid "OTP secret key" +msgstr "" + +#: users/models/user.py:912 users/serializers/profile.py:129 +#: users/serializers/user.py:179 +msgid "Is first login" +msgstr "" + +#: users/models/user.py:921 +msgid "Date password last updated" +msgstr "" + +#: users/models/user.py:924 +msgid "Need update password" +msgstr "" + +#: users/models/user.py:935 +msgid "Date api key used" +msgstr "" + +#: users/models/user.py:1057 +msgid "Can not delete admin user" +msgstr "" + +#: users/models/user.py:1071 +msgid "Can invite user" +msgstr "" + +#: users/models/user.py:1072 +msgid "Can remove user" +msgstr "" + +#: users/models/user.py:1073 +msgid "Can match user" +msgstr "" + +#: users/models/user.py:1082 +msgid "Administrator" +msgstr "" + +#: users/models/user.py:1085 +msgid "Administrator is the super user of system" +msgstr "" + +#: users/models/user.py:1110 +msgid "User password history" +msgstr "" + +#: users/notifications.py:55 +#: users/templates/users/_msg_password_expire_reminder.html:17 +#: users/templates/users/reset_password.html:5 +#: users/templates/users/reset_password.html:6 +msgid "Reset password" +msgstr "" + +#: users/notifications.py:85 users/views/profile/reset.py:233 +msgid "Reset password success" +msgstr "" + +#: users/notifications.py:117 +msgid "Reset public key success" +msgstr "" + +#: users/notifications.py:143 +msgid "Password is about expire" +msgstr "" + +#: users/notifications.py:171 +msgid "Account is about expire" +msgstr "" + +#: users/notifications.py:193 +msgid "Reset SSH Key" +msgstr "" + +#: users/notifications.py:214 +msgid "Reset MFA" +msgstr "" + +#: users/serializers/preference/koko.py:10 +msgid "File name conflict resolution" +msgstr "" + +#: users/serializers/preference/koko.py:14 +msgid "Terminal theme name" +msgstr "" + +#: users/serializers/preference/lina.py:13 +msgid "New file encryption password" +msgstr "" + +#: users/serializers/preference/lina.py:18 +msgid "Confirm file encryption password" +msgstr "" + +#: users/serializers/preference/lina.py:31 users/serializers/profile.py:48 +msgid "The newly set password is inconsistent" +msgstr "" + +#: users/serializers/preference/luna.py:26 +msgid "Async loading of asset tree" +msgstr "" + +#: users/serializers/preference/luna.py:30 +msgid "Connect default open method" +msgstr "" + +#: users/serializers/preference/luna.py:37 +msgid "RDP resolution" +msgstr "" + +#: users/serializers/preference/luna.py:41 +msgid "Keyboard layout" +msgstr "" + +#: users/serializers/preference/luna.py:45 +msgid "RDP client option" +msgstr "" + +#: users/serializers/preference/luna.py:49 +msgid "RDP color quality" +msgstr "" + +#: users/serializers/preference/luna.py:53 +msgid "RDP smart size" +msgstr "" + +#: users/serializers/preference/luna.py:54 +msgid "" +"Determines whether the client computer should scale the content on the " +"remote computer to fit the window size of the client computer when the " +"window is resized." +msgstr "" + +#: users/serializers/preference/luna.py:59 +msgid "Remote application connection method" +msgstr "" + +#: users/serializers/preference/luna.py:66 +msgid "Character terminal font size" +msgstr "" + +#: users/serializers/preference/luna.py:69 +msgid "Backspace as Ctrl+H" +msgstr "" + +#: users/serializers/preference/luna.py:72 +msgid "Right click quickly paste" +msgstr "" + +#: users/serializers/preference/luna.py:78 +msgid "Graphics" +msgstr "" + +#: users/serializers/preference/luna.py:79 +msgid "Command line" +msgstr "" + +#: users/serializers/profile.py:29 +msgid "The old password is incorrect" +msgstr "" + +#: users/serializers/profile.py:36 users/serializers/profile.py:179 +msgid "Password does not match security rules" +msgstr "" + +#: users/serializers/profile.py:40 +msgid "The new password cannot be the last {} passwords" +msgstr "" + +#: users/serializers/user.py:45 +msgid "System roles" +msgstr "" + +#: users/serializers/user.py:49 +msgid "Org roles" +msgstr "" + +#: users/serializers/user.py:52 +msgid "Organizations and roles" +msgstr "" + +#: users/serializers/user.py:94 +msgid "Password setting" +msgstr "" + +#: users/serializers/user.py:96 +msgid "MFA enabled" +msgstr "" + +#: users/serializers/user.py:98 +msgid "MFA force enabled" +msgstr "" + +#: users/serializers/user.py:100 +msgid "Login blocked" +msgstr "" + +#: users/serializers/user.py:103 users/serializers/user.py:188 +msgid "Is OTP bound" +msgstr "" + +#: users/serializers/user.py:104 +msgid "Super Administrator" +msgstr "" + +#: users/serializers/user.py:105 +msgid "Organization Administrator" +msgstr "" + +#: users/serializers/user.py:107 +msgid "Can public key authentication" +msgstr "" + +#: users/serializers/user.py:176 +msgid "Superuser" +msgstr "" + +#: users/serializers/user.py:183 +msgid "Is org admin" +msgstr "" + +#: users/serializers/user.py:185 +msgid "Avatar url" +msgstr "" + +#: users/serializers/user.py:189 +msgid "MFA level" +msgstr "" + +#: users/serializers/user.py:312 +msgid "" +"For security, only a partial of users is displayed. You can search for more" +msgstr "" + +#: users/serializers/user.py:345 +msgid "name not unique" +msgstr "" + +#: users/signal_handlers.py:35 +msgid "" +"The administrator has enabled \"Only allow existing users to log in\", \n" +" and the current user is not in the user list. Please contact the " +"administrator." +msgstr "" + +#: users/signal_handlers.py:169 +msgid "Clean up expired user sessions" +msgstr "" + +#: users/tasks.py:25 +msgid "Check password expired" +msgstr "" + +#: users/tasks.py:39 +msgid "Periodic check password expired" +msgstr "" + +#: users/tasks.py:53 +msgid "Check user expired" +msgstr "" + +#: users/tasks.py:70 +msgid "Periodic check user expired" +msgstr "" + +#: users/tasks.py:84 +msgid "Check unused users" +msgstr "" + +#: users/tasks.py:123 +msgid "The user has not logged in recently and has been disabled." +msgstr "" + +#: users/templates/users/_msg_account_expire_reminder.html:7 +msgid "Your account will expire in" +msgstr "" + +#: users/templates/users/_msg_account_expire_reminder.html:8 +msgid "" +"In order not to affect your normal work, please contact the administrator " +"for confirmation." +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:7 +msgid "Your password will expire in" +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:8 +msgid "" +"For your account security, please click on the link below to update your " +"password in time" +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:11 +msgid "Click here update password" +msgstr "" + +#: users/templates/users/_msg_password_expire_reminder.html:16 +msgid "If your password has expired, please click the link below to" +msgstr "" + +#: users/templates/users/_msg_reset_mfa.html:7 +msgid "Your MFA has been reset by site administrator" +msgstr "" + +#: users/templates/users/_msg_reset_mfa.html:8 +#: users/templates/users/_msg_reset_ssh_key.html:8 +msgid "Please click the link below to set" +msgstr "" + +#: users/templates/users/_msg_reset_mfa.html:11 +#: users/templates/users/_msg_reset_ssh_key.html:11 +msgid "Click here set" +msgstr "" + +#: users/templates/users/_msg_reset_ssh_key.html:7 +msgid "Your ssh public key has been reset by site administrator" +msgstr "" + +#: users/templates/users/_msg_user_created.html:15 +msgid "click here to set your password" +msgstr "" + +#: users/templates/users/forgot_password.html:46 +msgid "Input your email account, that will send a email to your" +msgstr "" + +#: users/templates/users/forgot_password.html:49 +msgid "" +"Enter your mobile number and a verification code will be sent to your phone" +msgstr "" + +#: users/templates/users/forgot_password.html:71 +msgid "Email account" +msgstr "" + +#: users/templates/users/forgot_password.html:93 +msgid "Mobile number" +msgstr "" + +#: users/templates/users/forgot_password.html:101 +msgid "Send" +msgstr "" + +#: users/templates/users/forgot_password.html:105 +#: users/templates/users/forgot_password_previewing.html:30 +msgid "Submit" +msgstr "" + +#: users/templates/users/forgot_password_previewing.html:21 +msgid "Please enter the username for which you want to retrieve the password" +msgstr "" + +#: users/templates/users/mfa_setting.html:24 +msgid "Enable MFA" +msgstr "" + +#: users/templates/users/mfa_setting.html:30 +msgid "MFA force enable, cannot disable" +msgstr "" + +#: users/templates/users/mfa_setting.html:48 +msgid "MFA setting" +msgstr "" + +#: users/templates/users/mfa_setting.html:61 +msgid "Reset" +msgstr "" + +#: users/templates/users/reset_password.html:23 +msgid "Your password must satisfy" +msgstr "" + +#: users/templates/users/reset_password.html:24 +msgid "Password strength" +msgstr "" + +#: users/templates/users/reset_password.html:48 +msgid "Very weak" +msgstr "" + +#: users/templates/users/reset_password.html:49 +msgid "Weak" +msgstr "" + +#: users/templates/users/reset_password.html:51 +msgid "Medium" +msgstr "" + +#: users/templates/users/reset_password.html:52 +msgid "Strong" +msgstr "" + +#: users/templates/users/reset_password.html:53 +msgid "Very strong" +msgstr "" + +#: users/templates/users/user_otp_check_password.html:6 +msgid "Enable OTP" +msgstr "" + +#: users/templates/users/user_otp_enable_bind.html:6 +msgid "Bind one-time password authenticator" +msgstr "" + +#: users/templates/users/user_otp_enable_bind.html:13 +msgid "" +"Use the MFA Authenticator application to scan the following qr code for a 6-" +"bit verification code" +msgstr "" + +#: users/templates/users/user_otp_enable_bind.html:22 +#: users/templates/users/user_verify_mfa.html:27 +msgid "Six figures" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:6 +msgid "Install app" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:13 +msgid "" +"Download and install the MFA Authenticator application on your phone or " +"applet of WeChat" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:18 +msgid "Android downloads" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:23 +msgid "iPhone downloads" +msgstr "" + +#: users/templates/users/user_otp_enable_install_app.html:27 +msgid "" +"After installation, click the next step to enter the binding page (if " +"installed, go to the next step directly)." +msgstr "" + +#: users/templates/users/user_password_verify.html:8 +#: users/templates/users/user_password_verify.html:9 +msgid "Verify password" +msgstr "" + +#: users/templates/users/user_verify_mfa.html:9 +msgid "Authenticate" +msgstr "" + +#: users/templates/users/user_verify_mfa.html:15 +msgid "" +"The account protection has been opened, please complete the following " +"operations according to the prompts" +msgstr "" + +#: users/templates/users/user_verify_mfa.html:17 +msgid "Open MFA Authenticator and enter the 6-bit dynamic code" +msgstr "" + +#: users/views/profile/otp.py:106 +msgid "Already bound" +msgstr "" + +#: users/views/profile/otp.py:107 +msgid "MFA already bound, disable first, then bound" +msgstr "" + +#: users/views/profile/otp.py:134 +msgid "OTP enable success" +msgstr "" + +#: users/views/profile/otp.py:135 +msgid "OTP enable success, return login page" +msgstr "" + +#: users/views/profile/otp.py:177 +msgid "Disable OTP" +msgstr "" + +#: users/views/profile/otp.py:183 +msgid "OTP disable success" +msgstr "" + +#: users/views/profile/otp.py:184 +msgid "OTP disable success, return login page" +msgstr "" + +#: users/views/profile/password.py:33 users/views/profile/password.py:38 +msgid "Password invalid" +msgstr "" + +#: users/views/profile/reset.py:66 +msgid "" +"Non-local users can log in only from third-party platforms and cannot change " +"their passwords: {}" +msgstr "" + +#: users/views/profile/reset.py:188 users/views/profile/reset.py:199 +msgid "Token invalid or expired" +msgstr "" + +#: users/views/profile/reset.py:204 +msgid "User auth from {}, go there change password" +msgstr "" + +#: users/views/profile/reset.py:211 +msgid "* Your password does not meet the requirements" +msgstr "" + +#: users/views/profile/reset.py:217 +msgid "* The new password cannot be the last {} passwords" +msgstr "" + +#: users/views/profile/reset.py:234 +msgid "Reset password success, return to login page" +msgstr "" + +#: xpack/apps.py:8 +msgid "XPACK" +msgstr "" + +#: xpack/exceptions.py:7 +msgid "" +"The current task is not synchronized with unmatched policy assets, skipping" +msgstr "" + +#: xpack/plugins/cloud/api.py:56 +msgid "Test connection successful" +msgstr "" + +#: xpack/plugins/cloud/api.py:58 +msgid "Test connection failed: {}" +msgstr "" + +#: xpack/plugins/cloud/const.py:8 +msgid "Alibaba Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:9 +msgid "AWS (International)" +msgstr "" + +#: xpack/plugins/cloud/const.py:10 +msgid "AWS (China)" +msgstr "" + +#: xpack/plugins/cloud/const.py:11 +msgid "Azure (China)" +msgstr "" + +#: xpack/plugins/cloud/const.py:12 +msgid "Azure (International)" +msgstr "" + +#: xpack/plugins/cloud/const.py:14 +msgid "Baidu Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:15 +msgid "JD Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:16 +msgid "KingSoft Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:17 +msgid "Tencent Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:18 +msgid "Tencent Cloud (Lighthouse)" +msgstr "" + +#: xpack/plugins/cloud/const.py:19 +msgid "Google Cloud Platform" +msgstr "" + +#: xpack/plugins/cloud/const.py:20 +msgid "UCloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:22 +msgid "VMware" +msgstr "" + +#: xpack/plugins/cloud/const.py:23 xpack/plugins/cloud/providers/nutanix.py:15 +msgid "Nutanix" +msgstr "" + +#: xpack/plugins/cloud/const.py:24 +msgid "Huawei Private Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:25 +msgid "Qingyun Private Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:26 +msgid "CTYun Private Cloud" +msgstr "" + +#: xpack/plugins/cloud/const.py:27 +msgid "OpenStack" +msgstr "" + +#: xpack/plugins/cloud/const.py:28 xpack/plugins/cloud/providers/zstack.py:21 +msgid "ZStack" +msgstr "" + +#: xpack/plugins/cloud/const.py:29 +msgid "Fusion Compute" +msgstr "" + +#: xpack/plugins/cloud/const.py:30 +msgid "SCP" +msgstr "" + +#: xpack/plugins/cloud/const.py:31 +msgid "Apsara Stack" +msgstr "" + +#: xpack/plugins/cloud/const.py:36 +msgid "Private IP" +msgstr "" + +#: xpack/plugins/cloud/const.py:37 +msgid "Public IP" +msgstr "" + +#: xpack/plugins/cloud/const.py:41 xpack/plugins/cloud/models.py:303 +msgid "Instance name" +msgstr "" + +#: xpack/plugins/cloud/const.py:42 +msgid "Instance name and Partial IP" +msgstr "" + +#: xpack/plugins/cloud/const.py:47 +msgid "Succeed" +msgstr "" + +#: xpack/plugins/cloud/const.py:51 +msgid "Unsync" +msgstr "" + +#: xpack/plugins/cloud/const.py:52 +msgid "New Sync" +msgstr "" + +#: xpack/plugins/cloud/const.py:53 +msgid "Synced" +msgstr "" + +#: xpack/plugins/cloud/const.py:54 +msgid "Released" +msgstr "" + +#: xpack/plugins/cloud/const.py:58 +msgid "And" +msgstr "" + +#: xpack/plugins/cloud/const.py:59 +msgid "Or" +msgstr "" + +#: xpack/plugins/cloud/manager.py:56 +msgid "Account unavailable" +msgstr "" + +#: xpack/plugins/cloud/meta.py:9 +msgid "Cloud center" +msgstr "" + +#: xpack/plugins/cloud/models.py:34 +msgid "Provider" +msgstr "" + +#: xpack/plugins/cloud/models.py:37 +#: xpack/plugins/cloud/serializers/account.py:67 +msgid "Attrs" +msgstr "" + +#: xpack/plugins/cloud/models.py:38 +msgid "Validity" +msgstr "" + +#: xpack/plugins/cloud/models.py:43 +msgid "Cloud account" +msgstr "" + +#: xpack/plugins/cloud/models.py:45 +msgid "Test cloud account" +msgstr "" + +#: xpack/plugins/cloud/models.py:92 xpack/plugins/cloud/serializers/task.py:159 +msgid "Regions" +msgstr "" + +#: xpack/plugins/cloud/models.py:95 +msgid "Hostname strategy" +msgstr "" + +#: xpack/plugins/cloud/models.py:100 +#: xpack/plugins/cloud/serializers/task.py:162 +msgid "IP network segment group" +msgstr "" + +#: xpack/plugins/cloud/models.py:103 +#: xpack/plugins/cloud/serializers/task.py:167 +msgid "Sync IP type" +msgstr "" + +#: xpack/plugins/cloud/models.py:106 +#: xpack/plugins/cloud/serializers/task.py:185 +msgid "Always update" +msgstr "" + +#: xpack/plugins/cloud/models.py:108 +msgid "Fully synchronous" +msgstr "" + +#: xpack/plugins/cloud/models.py:113 +msgid "Date last sync" +msgstr "" + +#: xpack/plugins/cloud/models.py:116 xpack/plugins/cloud/models.py:321 +#: xpack/plugins/cloud/models.py:345 +msgid "Strategy" +msgstr "" + +#: xpack/plugins/cloud/models.py:121 xpack/plugins/cloud/models.py:200 +msgid "Sync instance task" +msgstr "" + +#: xpack/plugins/cloud/models.py:211 xpack/plugins/cloud/models.py:263 +msgid "Date sync" +msgstr "" + +#: xpack/plugins/cloud/models.py:215 +msgid "Sync instance snapshot" +msgstr "" + +#: xpack/plugins/cloud/models.py:219 +msgid "Sync instance task execution" +msgstr "" + +#: xpack/plugins/cloud/models.py:243 +msgid "Sync task" +msgstr "" + +#: xpack/plugins/cloud/models.py:247 +msgid "Sync instance task history" +msgstr "" + +#: xpack/plugins/cloud/models.py:250 +msgid "Instance" +msgstr "" + +#: xpack/plugins/cloud/models.py:267 +msgid "Sync instance detail" +msgstr "" + +#: xpack/plugins/cloud/models.py:279 xpack/plugins/cloud/serializers/task.py:72 +msgid "Rule relation" +msgstr "" + +#: xpack/plugins/cloud/models.py:288 +msgid "Task strategy" +msgstr "" + +#: xpack/plugins/cloud/models.py:292 +msgid "Equal" +msgstr "" + +#: xpack/plugins/cloud/models.py:293 +msgid "Not Equal" +msgstr "" + +#: xpack/plugins/cloud/models.py:294 +msgid "In" +msgstr "" + +#: xpack/plugins/cloud/models.py:295 +msgid "Contains" +msgstr "" + +#: xpack/plugins/cloud/models.py:296 +msgid "Exclude" +msgstr "" + +#: xpack/plugins/cloud/models.py:297 +msgid "Startswith" +msgstr "" + +#: xpack/plugins/cloud/models.py:298 +msgid "Endswith" +msgstr "" + +#: xpack/plugins/cloud/models.py:304 +msgid "Instance platform" +msgstr "" + +#: xpack/plugins/cloud/models.py:305 +msgid "Instance address" +msgstr "" + +#: xpack/plugins/cloud/models.py:312 +msgid "Rule attr" +msgstr "" + +#: xpack/plugins/cloud/models.py:316 +msgid "Rule match" +msgstr "" + +#: xpack/plugins/cloud/models.py:318 +msgid "Rule value" +msgstr "" + +#: xpack/plugins/cloud/models.py:325 xpack/plugins/cloud/serializers/task.py:75 +msgid "Strategy rule" +msgstr "" + +#: xpack/plugins/cloud/models.py:340 +msgid "Action attr" +msgstr "" + +#: xpack/plugins/cloud/models.py:342 +msgid "Action value" +msgstr "" + +#: xpack/plugins/cloud/models.py:349 xpack/plugins/cloud/serializers/task.py:78 +msgid "Strategy action" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:18 +msgid "China (Beijing)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:19 +msgid "China (Ningxia)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:22 +msgid "US East (Ohio)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:23 +msgid "US East (N. Virginia)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:24 +msgid "US West (N. California)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:25 +msgid "US West (Oregon)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:26 +msgid "Africa (Cape Town)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:27 +msgid "Asia Pacific (Hong Kong)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:28 +msgid "Asia Pacific (Mumbai)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:29 +msgid "Asia Pacific (Osaka-Local)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:30 +msgid "Asia Pacific (Seoul)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:31 +msgid "Asia Pacific (Singapore)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:32 +msgid "Asia Pacific (Sydney)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:33 +msgid "Asia Pacific (Tokyo)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:34 +msgid "Canada (Central)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:35 +msgid "Europe (Frankfurt)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:36 +msgid "Europe (Ireland)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:37 +msgid "Europe (London)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:38 +msgid "Europe (Milan)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:39 +msgid "Europe (Paris)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:40 +msgid "Europe (Stockholm)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:41 +msgid "Middle East (Bahrain)" +msgstr "" + +#: xpack/plugins/cloud/providers/aws_international.py:42 +msgid "South America (São Paulo)" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:54 +#: xpack/plugins/cloud/providers/jdcloud.py:125 +msgid "CN North-Beijing" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:55 +#: xpack/plugins/cloud/providers/huaweicloud.py:42 +#: xpack/plugins/cloud/providers/jdcloud.py:128 +msgid "CN South-Guangzhou" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:56 +msgid "CN East-Suzhou" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:57 +#: xpack/plugins/cloud/providers/huaweicloud.py:49 +msgid "CN-Hong Kong" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:58 +msgid "CN Center-Wuhan" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:59 +msgid "CN North-Baoding" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:60 +#: xpack/plugins/cloud/providers/jdcloud.py:127 +msgid "CN East-Shanghai" +msgstr "" + +#: xpack/plugins/cloud/providers/baiducloud.py:61 +#: xpack/plugins/cloud/providers/huaweicloud.py:51 +msgid "AP-Singapore" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:39 +msgid "CN North-Beijing1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:40 +msgid "CN North-Beijing4" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:41 +msgid "CN North-Ulanqab1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:43 +msgid "CN South-Shenzhen" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:44 +msgid "CN South-Guangzhou-InvitationOnly" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:45 +msgid "CN East-Shanghai2" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:46 +msgid "CN East-Shanghai1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:48 +msgid "CN Southwest-Guiyang1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:50 +msgid "AP-Bangkok" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:53 +msgid "AF-Johannesburg" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:54 +msgid "LA-Mexico City1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:55 +msgid "LA-Santiago" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:56 +msgid "LA-Sao Paulo1" +msgstr "" + +#: xpack/plugins/cloud/providers/huaweicloud.py:58 +msgid "TR-Istanbul" +msgstr "" + +#: xpack/plugins/cloud/providers/jdcloud.py:126 +msgid "CN East-Suqian" +msgstr "" + +#: xpack/plugins/cloud/serializers/account.py:68 +msgid "Validity display" +msgstr "" + +#: xpack/plugins/cloud/serializers/account.py:69 +msgid "Provider display" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:17 +msgid "Access key id" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:35 +msgid "Client ID" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:41 +msgid "Tenant ID" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:44 +msgid "Subscription ID" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:98 +#: xpack/plugins/cloud/serializers/account_attrs.py:102 +#: xpack/plugins/cloud/serializers/account_attrs.py:126 +#: xpack/plugins/cloud/serializers/account_attrs.py:156 +#: xpack/plugins/cloud/serializers/account_attrs.py:206 +msgid "API Endpoint" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:108 +msgid "Auth url" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:109 +msgid "eg: http://openstack.example.com:5000/v3" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:112 +msgid "User domain" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:127 +msgid "Cert File" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:128 +msgid "Key File" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:144 +msgid "Service account key" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:145 +msgid "The file is in JSON format" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:163 +msgid "IP address invalid `{}`, {}" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:179 +msgid "Such as: 192.168.1.0/24, 10.0.0.0-10.0.0.255" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:182 +msgid "" +"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 " +"synchronized.
If the port is 0, all IP addresses are valid." +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:190 +msgid "Hostname prefix" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:193 +msgid "IP segment" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:197 +msgid "Test port" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:200 +msgid "Test timeout" +msgstr "" + +#: xpack/plugins/cloud/serializers/account_attrs.py:216 +msgid "Project" +msgstr "" + +#: xpack/plugins/cloud/serializers/task.py:151 +msgid "" +"Only instances matching the IP range will be synced.
If the instance " +"contains multiple IP addresses, the first IP address that matches will be " +"used as the IP for the created asset.
The default value of * means sync " +"all instances and randomly match IP addresses.
Such as: 192.168.1.0/24, " +"10.1.1.1-10.1.1.20" +msgstr "" + +#: xpack/plugins/cloud/serializers/task.py:157 +msgid "History count" +msgstr "" + +#: xpack/plugins/cloud/serializers/task.py:158 +msgid "Instance count" +msgstr "" + +#: xpack/plugins/cloud/tasks.py:27 +msgid "Run sync instance task" +msgstr "" + +#: xpack/plugins/cloud/tasks.py:41 +msgid "Period clean sync instance task execution" +msgstr "" + +#: xpack/plugins/interface/api.py:52 +msgid "Restore default successfully." +msgstr "" + +#: xpack/plugins/interface/meta.py:9 +msgid "Interface settings" +msgstr "" + +#: xpack/plugins/interface/models.py:23 +msgid "Login title" +msgstr "" + +#: xpack/plugins/interface/models.py:27 +msgid "Login image" +msgstr "" + +#: xpack/plugins/interface/models.py:31 +msgid "Website icon" +msgstr "" + +#: xpack/plugins/interface/models.py:35 +msgid "Index logo" +msgstr "" + +#: xpack/plugins/interface/models.py:39 +msgid "Logout logo" +msgstr "" + +#: xpack/plugins/interface/models.py:41 +#: xpack/plugins/interface/serializers/interface.py:26 +msgid "Theme" +msgstr "" + +#: xpack/plugins/interface/models.py:42 +msgid "Beian link" +msgstr "" + +#: xpack/plugins/interface/models.py:43 +msgid "Beian text" +msgstr "" + +#: xpack/plugins/interface/models.py:46 xpack/plugins/interface/models.py:87 +msgid "Interface setting" +msgstr "" + +#: xpack/plugins/interface/serializers/interface.py:37 +msgid "Wide logo on top" +msgstr "" + +#: xpack/plugins/interface/serializers/interface.py:38 +msgid "Small logo without text" +msgstr "" + +#: xpack/plugins/license/api.py:52 +msgid "License import successfully" +msgstr "" + +#: xpack/plugins/license/api.py:53 +msgid "License is invalid" +msgstr "" + +#: xpack/plugins/license/meta.py:10 xpack/plugins/license/models.py:144 +msgid "License" +msgstr "" + +#: xpack/plugins/license/models.py:80 +msgid "Basic edition" +msgstr "" + +#: xpack/plugins/license/models.py:82 +msgid "Standard edition" +msgstr "" + +#: xpack/plugins/license/models.py:84 +msgid "Professional edition" +msgstr "" + +#: xpack/plugins/license/models.py:86 +msgid "Ultimate edition" +msgstr "" diff --git a/apps/notifications/migrations/0001_initial.py b/apps/notifications/migrations/0001_initial.py index e63e4f36a..5eb248d4b 100644 --- a/apps/notifications/migrations/0001_initial.py +++ b/apps/notifications/migrations/0001_initial.py @@ -1,8 +1,6 @@ -# Generated by Django 3.1 on 2021-05-31 08:59 +# Generated by Django 4.1.13 on 2024-05-09 03:16 -from django.conf import settings from django.db import migrations, models -import django.db.models.deletion import uuid @@ -11,82 +9,67 @@ class Migration(migrations.Migration): initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('users', '0035_auto_20210526_1100'), ] operations = [ migrations.CreateModel( - name='SiteMessage', + name='MessageContent', fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), + ('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)), ('subject', models.CharField(max_length=1024)), ('message', models.TextField()), ('is_broadcast', models.BooleanField(default=False)), - ('groups', models.ManyToManyField(to='users.UserGroup')), - ('sender', models.ForeignKey(db_constraint=False, default=None, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='send_site_message', to=settings.AUTH_USER_MODEL)), ], options={ 'abstract': False, }, ), migrations.CreateModel( - name='UserMsgSubscription', + name='SiteMessage', fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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)), - ('message_type', models.CharField(max_length=128)), - ('receive_backends', models.JSONField(default=list, verbose_name='receive backend')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user_msg_subscription', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'abstract': False, 'verbose_name': 'User message' - }, - ), - migrations.CreateModel( - name='SystemMsgSubscription', - fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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)), - ('message_type', models.CharField(max_length=128, unique=True)), - ('receive_backends', models.JSONField(default=list)), - ('groups', models.ManyToManyField(related_name='system_msg_subscriptions', to='users.UserGroup')), - ('users', models.ManyToManyField(related_name='system_msg_subscriptions', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'abstract': False, 'verbose_name': 'System message' - }, - ), - migrations.CreateModel( - name='SiteMessageUsers', - fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), + ('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)), ('has_read', models.BooleanField(default=False)), ('read_at', models.DateTimeField(default=None, null=True)), - ('sitemessage', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, related_name='m2m_sitemessageusers', to='notifications.sitemessage')), - ('user', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, related_name='m2m_sitemessageusers', to=settings.AUTH_USER_MODEL)), ], options={ 'abstract': False, }, ), - migrations.AddField( - model_name='sitemessage', - name='users', - field=models.ManyToManyField(related_name='recv_site_messages', through='notifications.SiteMessageUsers', to=settings.AUTH_USER_MODEL), + migrations.CreateModel( + name='SystemMsgSubscription', + 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)), + ('message_type', models.CharField(max_length=128, unique=True)), + ('receive_backends', models.JSONField(default=list)), + ], + options={ + 'verbose_name': 'System message', + }, + ), + migrations.CreateModel( + name='UserMsgSubscription', + 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)), + ('receive_backends', models.JSONField(default=list, verbose_name='receive backend')), + ], + options={ + 'verbose_name': 'User message', + }, ), ] diff --git a/apps/notifications/migrations/0002_auto_20210909_1946.py b/apps/notifications/migrations/0002_auto_20210909_1946.py index ef198dc89..6145b3471 100644 --- a/apps/notifications/migrations/0002_auto_20210909_1946.py +++ b/apps/notifications/migrations/0002_auto_20210909_1946.py @@ -1,55 +1,60 @@ -# Generated by Django 3.1.12 on 2021-09-09 11:46 +# Generated by Django 4.1.13 on 2024-05-09 03:16 import common.db.models from django.conf import settings from django.db import migrations, models - - -def init_user_msg_subscription(apps, schema_editor): - UserMsgSubscription = apps.get_model('notifications', 'UserMsgSubscription') - User = apps.get_model('users', 'User') - - to_create = [] - users = User.objects.all() - for user in users: - receive_backends = [] - - receive_backends.append('site_msg') - - if user.email: - receive_backends.append('email') - - if user.wecom_id: - receive_backends.append('wecom') - - if user.dingtalk_id: - receive_backends.append('dingtalk') - - if user.feishu_id: - receive_backends.append('feishu') - - to_create.append(UserMsgSubscription(user=user, receive_backends=receive_backends)) - UserMsgSubscription.objects.bulk_create(to_create) - print(f'\n\tInit user message subscription: {len(to_create)}') +import django.db.models.deletion class Migration(migrations.Migration): + initial = True + dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('users', '0001_initial'), ('notifications', '0001_initial'), - ('users', '0036_user_feishu_id'), ] operations = [ - migrations.RemoveField( - model_name='usermsgsubscription', - name='message_type', - ), - migrations.AlterField( + migrations.AddField( model_name='usermsgsubscription', name='user', field=models.OneToOneField(on_delete=common.db.models.CASCADE_SIGNAL_SKIP, related_name='user_msg_subscription', to=settings.AUTH_USER_MODEL, verbose_name='User'), ), - migrations.RunPython(init_user_msg_subscription) + migrations.AddField( + model_name='systemmsgsubscription', + name='groups', + field=models.ManyToManyField(related_name='system_msg_subscriptions', to='users.usergroup'), + ), + migrations.AddField( + model_name='systemmsgsubscription', + name='users', + field=models.ManyToManyField(related_name='system_msg_subscriptions', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='sitemessage', + name='content', + field=models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='notifications.messagecontent'), + ), + migrations.AddField( + model_name='sitemessage', + name='user', + field=models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='messagecontent', + name='groups', + field=models.ManyToManyField(to='users.usergroup'), + ), + migrations.AddField( + model_name='messagecontent', + name='sender', + field=models.ForeignKey(db_constraint=False, default=None, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='send_site_message', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='messagecontent', + name='users', + field=models.ManyToManyField(related_name='recv_site_messages', through='notifications.SiteMessage', to=settings.AUTH_USER_MODEL), + ), ] diff --git a/apps/notifications/migrations/0003_auto_20221220_1956.py b/apps/notifications/migrations/0003_auto_20221220_1956.py deleted file mode 100644 index 7cbac3e18..000000000 --- a/apps/notifications/migrations/0003_auto_20221220_1956.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('notifications', '0002_auto_20210909_1946'), - ] - - operations = [ - migrations.AlterField( - model_name='sitemessage', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='sitemessage', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='sitemessageusers', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='sitemessageusers', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='systemmsgsubscription', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='systemmsgsubscription', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='usermsgsubscription', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='usermsgsubscription', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - ] diff --git a/apps/notifications/migrations/0004_auto_20230201_1614.py b/apps/notifications/migrations/0004_auto_20230201_1614.py deleted file mode 100644 index a59aeb8c2..000000000 --- a/apps/notifications/migrations/0004_auto_20230201_1614.py +++ /dev/null @@ -1,72 +0,0 @@ -# Generated by Django 3.2.14 on 2023-02-01 08:14 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('users', '0041_auto_20221220_1956'), - ('notifications', '0003_auto_20221220_1956'), - ] - - operations = [ - migrations.RemoveField( - model_name='sitemessageusers', - name='sitemessage', - ), - migrations.RemoveField( - model_name='sitemessageusers', - name='user', - ), - migrations.DeleteModel( - name='SiteMessage', - ), - migrations.DeleteModel( - name='SiteMessageUsers', - ), - migrations.CreateModel( - name='MessageContent', - 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)), - ('subject', models.CharField(max_length=1024)), - ('message', models.TextField()), - ('is_broadcast', models.BooleanField(default=False)), - ('groups', models.ManyToManyField(to='users.UserGroup')), - ('sender', models.ForeignKey(db_constraint=False, default=None, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='send_site_message', to=settings.AUTH_USER_MODEL)), - ], - options={ - 'abstract': False, - }, - ), - migrations.CreateModel( - name='SiteMessage', - 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)), - ('has_read', models.BooleanField(default=False)), - ('read_at', models.DateTimeField(default=None, null=True)), - ('content', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='notifications.messagecontent')), - ('user', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'abstract': False, - }, - ), - migrations.AddField( - model_name='messagecontent', - name='users', - field=models.ManyToManyField(related_name='recv_site_messages', through='notifications.SiteMessage', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/apps/notifications/signal_handlers.py b/apps/notifications/signal_handlers.py index 797724755..bd4433937 100644 --- a/apps/notifications/signal_handlers.py +++ b/apps/notifications/signal_handlers.py @@ -70,9 +70,14 @@ def create_system_messages(app_config: AppConfig, **kwargs): message_type = obj.get_message_type() sub, created = SystemMsgSubscription.objects.get_or_create(message_type=message_type) - if created: + if not created: + return + + try: obj.post_insert_to_db(sub) logger.info(f'Create MsgSubscription: package={app_config.module.__package__} type={message_type}') + except: + pass except ModuleNotFoundError: pass diff --git a/apps/ops/migrations/0001_initial.py b/apps/ops/migrations/0001_initial.py index 56a6030ba..0cf60bd26 100644 --- a/apps/ops/migrations/0001_initial.py +++ b/apps/ops/migrations/0001_initial.py @@ -1,9 +1,10 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2017-12-24 15:21 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 +import common.db.encoder from django.db import migrations, models -import django.db.models.deletion +import private_storage.fields +import private_storage.storage.files +import simple_history.models import uuid @@ -18,67 +19,165 @@ class Migration(migrations.Migration): migrations.CreateModel( name='AdHoc', 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')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('_tasks', models.TextField(verbose_name='Tasks')), - ('pattern', models.CharField(default='{}', max_length=64, verbose_name='Pattern')), - ('_options', models.CharField(default='', max_length=1024, verbose_name='Options')), - ('_hosts', models.TextField(blank=True, verbose_name='Hosts')), - ('run_as_admin', models.BooleanField(default=False, verbose_name='Run as admin')), - ('run_as', models.CharField(default='', max_length=128, verbose_name='Run as')), - ('_become', models.CharField(default='', max_length=1024, verbose_name='Become')), - ('created_by', models.CharField(default='', max_length=64, null=True, verbose_name='Create by')), - ('date_created', models.DateTimeField(auto_now_add=True)), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('pattern', models.CharField(default='all', max_length=1024, verbose_name='Pattern')), + ('module', models.CharField(choices=[('shell', 'Shell'), ('win_shell', 'Powershell'), ('python', 'Python'), ('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('oracle', 'Oracle'), ('raw', 'Raw')], default='shell', max_length=128, verbose_name='Module')), + ('args', models.CharField(default='', max_length=8192, verbose_name='Args')), + ('comment', models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Comment')), ], options={ - 'db_table': 'ops_adhoc', - 'get_latest_by': 'date_created', + 'verbose_name': 'Adhoc', }, ), migrations.CreateModel( - name='AdHocRunHistory', + name='CeleryTask', fields=[ ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('date_start', models.DateTimeField(auto_now_add=True, verbose_name='Start time')), - ('date_finished', models.DateTimeField(blank=True, null=True, verbose_name='End time')), - ('timedelta', models.FloatField(default=0.0, null=True, verbose_name='Time')), - ('is_finished', models.BooleanField(default=False, verbose_name='Is finished')), - ('is_success', models.BooleanField(default=False, verbose_name='Is success')), - ('_result', models.TextField(blank=True, null=True, verbose_name='Adhoc raw result')), - ('_summary', models.TextField(blank=True, null=True, verbose_name='Adhoc result summary')), - ('adhoc', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='history', to='ops.AdHoc')), + ('name', models.CharField(max_length=1024, verbose_name='Name')), + ('date_last_publish', models.DateTimeField(null=True, verbose_name='Date last publish')), ], options={ - 'db_table': 'ops_adhoc_history', - 'get_latest_by': 'date_start', + 'verbose_name': 'Celery Task', + 'ordering': ('name',), + 'permissions': [('view_taskmonitor', 'Can view task monitor')], }, ), migrations.CreateModel( - name='Task', + name='CeleryTaskExecution', fields=[ ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('interval', models.IntegerField(blank=True, help_text='Units: seconds', null=True, verbose_name='Interval')), - ('crontab', models.CharField(blank=True, help_text='5 * * * *', max_length=128, null=True, verbose_name='Crontab')), + ('name', models.CharField(max_length=1024, verbose_name='Name')), + ('args', models.JSONField(verbose_name='Args')), + ('kwargs', models.JSONField(verbose_name='Kwargs')), + ('state', models.CharField(max_length=16, verbose_name='State')), + ('is_finished', models.BooleanField(default=False, verbose_name='Finished')), + ('date_published', models.DateTimeField(auto_now_add=True, verbose_name='Date published')), + ('date_start', models.DateTimeField(null=True, verbose_name='Date start')), + ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), + ], + options={ + 'verbose_name': 'Celery Task Execution', + 'ordering': ['-date_start'], + }, + ), + migrations.CreateModel( + name='HistoricalJob', + 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(blank=True, editable=False, null=True, verbose_name='Date created')), + ('date_updated', models.DateTimeField(blank=True, editable=False, verbose_name='Date updated')), + ('id', models.UUIDField(db_index=True, default=uuid.uuid4)), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')), - ('callback', models.CharField(blank=True, max_length=128, null=True, verbose_name='Callback')), - ('is_deleted', models.BooleanField(default=False)), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('created_by', models.CharField(blank=True, default='', max_length=128, null=True)), - ('date_created', models.DateTimeField(auto_now_add=True)), + ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')), + ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')), + ('name', models.CharField(max_length=128, null=True, verbose_name='Name')), + ('instant', models.BooleanField(default=False)), + ('args', models.CharField(blank=True, default='', max_length=8192, null=True, verbose_name='Args')), + ('module', models.CharField(choices=[('shell', 'Shell'), ('win_shell', 'Powershell'), ('python', 'Python'), ('mysql', 'MySQL'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('raw', 'Raw'), ('huawei', 'HUAWEI')], default='shell', max_length=128, null=True, verbose_name='Module')), + ('chdir', models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Chdir')), + ('timeout', models.IntegerField(default=-1, verbose_name='Timeout (Seconds)')), + ('type', models.CharField(choices=[('adhoc', 'Adhoc'), ('playbook', 'Playbook'), ('upload_file', 'Upload File')], default='adhoc', max_length=128, verbose_name='Type')), + ('use_parameter_define', models.BooleanField(default=False, verbose_name='Use Parameter Define')), + ('parameters_define', models.JSONField(default=dict, verbose_name='Parameters define')), + ('runas', models.CharField(default='root', max_length=128, verbose_name='Runas')), + ('runas_policy', models.CharField(choices=[('privileged_only', 'Privileged Only'), ('privileged_first', 'Privileged First'), ('skip', 'Skip')], default='skip', max_length=128, verbose_name='Runas policy')), + ('comment', models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Comment')), + ('version', models.IntegerField(default=0)), + ('history_id', models.AutoField(primary_key=True, serialize=False)), + ('history_date', models.DateTimeField(db_index=True)), + ('history_change_reason', models.CharField(max_length=100, null=True)), + ('history_type', models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), ], options={ - 'db_table': 'ops_task', - 'get_latest_by': 'date_created', + 'verbose_name': 'historical Job', + 'verbose_name_plural': 'historical Jobs', + 'ordering': ('-history_date', '-history_id'), + 'get_latest_by': ('history_date', 'history_id'), + }, + bases=(simple_history.models.HistoricalChanges, models.Model), + ), + migrations.CreateModel( + name='Job', + 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')), + ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')), + ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')), + ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')), + ('name', models.CharField(max_length=128, null=True, verbose_name='Name')), + ('instant', models.BooleanField(default=False)), + ('args', models.CharField(blank=True, default='', max_length=8192, null=True, verbose_name='Args')), + ('module', models.CharField(choices=[('shell', 'Shell'), ('win_shell', 'Powershell'), ('python', 'Python'), ('mysql', 'MySQL'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('raw', 'Raw'), ('huawei', 'HUAWEI')], default='shell', max_length=128, null=True, verbose_name='Module')), + ('chdir', models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Chdir')), + ('timeout', models.IntegerField(default=-1, verbose_name='Timeout (Seconds)')), + ('type', models.CharField(choices=[('adhoc', 'Adhoc'), ('playbook', 'Playbook'), ('upload_file', 'Upload File')], default='adhoc', max_length=128, verbose_name='Type')), + ('use_parameter_define', models.BooleanField(default=False, verbose_name='Use Parameter Define')), + ('parameters_define', models.JSONField(default=dict, verbose_name='Parameters define')), + ('runas', models.CharField(default='root', max_length=128, verbose_name='Runas')), + ('runas_policy', models.CharField(choices=[('privileged_only', 'Privileged Only'), ('privileged_first', 'Privileged First'), ('skip', 'Skip')], default='skip', max_length=128, verbose_name='Runas policy')), + ('comment', models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Comment')), + ('version', models.IntegerField(default=0)), + ], + options={ + 'verbose_name': 'Job', + 'ordering': ['date_created'], }, ), - migrations.AddField( - model_name='adhocrunhistory', - name='task', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='history', to='ops.Task'), + migrations.CreateModel( + name='JobExecution', + 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_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('task_id', models.UUIDField(null=True)), + ('status', models.CharField(default='running', max_length=16, verbose_name='Status')), + ('job_version', models.IntegerField(default=0)), + ('parameters', models.JSONField(default=dict, verbose_name='Parameters')), + ('result', models.JSONField(blank=True, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True, verbose_name='Result')), + ('summary', models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, verbose_name='Summary')), + ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), + ('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')), + ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), + ('material', models.CharField(blank=True, default='', max_length=8192, null=True, verbose_name='Material')), + ('job_type', models.CharField(choices=[('adhoc', 'Adhoc'), ('playbook', 'Playbook'), ('upload_file', 'Upload File')], default='adhoc', max_length=128, verbose_name='Material Type')), + ], + options={ + 'verbose_name': 'Job Execution', + 'ordering': ['-date_created'], + }, ), - migrations.AddField( - model_name='adhoc', - name='task', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='adhoc', to='ops.Task'), + migrations.CreateModel( + name='Playbook', + 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')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, null=True, verbose_name='Name')), + ('path', private_storage.fields.PrivateFileField(storage=private_storage.storage.files.PrivateFileSystemStorage(), upload_to='playbooks/')), + ('comment', models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Comment')), + ('create_method', models.CharField(choices=[('blank', 'Blank'), ('vcs', 'VCS')], default='blank', max_length=128, verbose_name='CreateMethod')), + ('vcs_url', models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='VCS URL')), + ], + options={ + 'ordering': ['date_created'], + }, ), ] diff --git a/apps/ops/migrations/0002_celerytask.py b/apps/ops/migrations/0002_celerytask.py index 7ae3c14dc..70e442d90 100644 --- a/apps/ops/migrations/0002_celerytask.py +++ b/apps/ops/migrations/0002_celerytask.py @@ -1,28 +1,86 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-02 09:45 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 +from django.conf import settings from django.db import migrations, models -import uuid +import django.db.models.deletion class Migration(migrations.Migration): + initial = True + dependencies = [ ('ops', '0001_initial'), + ('assets', '0002_auto_20180105_1807'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.CreateModel( - name='CeleryTask', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=1024)), - ('status', models.CharField(choices=[('waiting', 'waiting'), ('running', 'running'), ('finished', 'finished')], max_length=128)), - ('log_path', models.CharField(blank=True, max_length=256, null=True)), - ('date_published', models.DateTimeField(auto_now_add=True)), - ('date_start', models.DateTimeField(null=True)), - ('date_finished', models.DateTimeField(null=True)), - ], + migrations.AddField( + model_name='playbook', + name='creator', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Creator'), + ), + migrations.AddField( + model_name='jobexecution', + name='creator', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Creator'), + ), + migrations.AddField( + model_name='jobexecution', + name='job', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='executions', to='ops.job'), + ), + migrations.AddField( + model_name='job', + name='assets', + field=models.ManyToManyField(to='assets.asset', verbose_name='Assets'), + ), + migrations.AddField( + model_name='job', + name='creator', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Creator'), + ), + migrations.AddField( + model_name='job', + name='playbook', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='ops.playbook', verbose_name='Playbook'), + ), + migrations.AddField( + model_name='historicaljob', + name='creator', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='Creator'), + ), + migrations.AddField( + model_name='historicaljob', + name='history_user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='historicaljob', + name='playbook', + field=models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', to='ops.playbook', verbose_name='Playbook'), + ), + migrations.AddField( + model_name='celerytaskexecution', + name='creator', + field=models.ForeignKey(db_constraint=False, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Creator'), + ), + migrations.AddField( + model_name='adhoc', + name='creator', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Creator'), + ), + migrations.AlterUniqueTogether( + name='playbook', + unique_together={('name', 'org_id', 'creator')}, + ), + migrations.AlterUniqueTogether( + name='job', + unique_together={('name', 'org_id', 'creator')}, + ), + migrations.AlterUniqueTogether( + name='adhoc', + unique_together={('name', 'org_id', 'creator')}, ), ] diff --git a/apps/ops/migrations/0003_auto_20181207_1744.py b/apps/ops/migrations/0003_auto_20181207_1744.py deleted file mode 100644 index d3ef032e9..000000000 --- a/apps/ops/migrations/0003_auto_20181207_1744.py +++ /dev/null @@ -1,56 +0,0 @@ -# Generated by Django 2.1.4 on 2018-12-07 09:44 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0023_auto_20181016_1650'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('ops', '0002_celerytask'), - ] - - operations = [ - migrations.CreateModel( - name='CommandExecution', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('command', models.TextField(verbose_name='Command')), - ('_result', models.TextField(blank=True, null=True, verbose_name='Result')), - ('is_finished', models.BooleanField(default=False)), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('date_start', models.DateTimeField(null=True)), - ('date_finished', models.DateTimeField(null=True)), - ('hosts', models.ManyToManyField(to='assets.Asset')), - ('run_as', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.SystemUser')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - ), - migrations.RemoveField( - model_name='adhoc', - name='run_as', - ), - migrations.AddField( - model_name='adhoc', - name='hosts', - field=models.ManyToManyField(to='assets.Asset', verbose_name='Host'), - ), - migrations.AlterField( - model_name='task', - name='created_by', - field=models.CharField(blank=True, default='', max_length=128), - ), - migrations.AlterField( - model_name='task', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='task', - unique_together={('name', 'created_by')}, - ), - ] diff --git a/apps/ops/migrations/0004_adhoc_run_as.py b/apps/ops/migrations/0004_adhoc_run_as.py deleted file mode 100644 index 8e49eaa2b..000000000 --- a/apps/ops/migrations/0004_adhoc_run_as.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 2.1.4 on 2018-12-07 09:44 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0023_auto_20181016_1650'), - ('ops', '0003_auto_20181207_1744'), - ] - - operations = [ - migrations.AddField( - model_name='adhoc', - name='run_as', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.SystemUser'), - ), - ] diff --git a/apps/ops/migrations/0005_auto_20181219_1807.py b/apps/ops/migrations/0005_auto_20181219_1807.py deleted file mode 100644 index 44442013f..000000000 --- a/apps/ops/migrations/0005_auto_20181219_1807.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 2.1 on 2018-12-19 10:07 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0004_adhoc_run_as'), - ] - - operations = [ - migrations.AlterField( - model_name='task', - name='date_created', - field=models.DateTimeField(auto_now_add=True, db_index=True), - ), - migrations.AlterField( - model_name='adhoc', - name='date_created', - field=models.DateTimeField(auto_now_add=True, db_index=True), - ), - migrations.AlterField( - model_name='celerytask', - name='status', - field=models.CharField( - choices=[('waiting', 'waiting'), ('running', 'running'), - ('finished', 'finished')], db_index=True, - max_length=128), - ), - ] diff --git a/apps/ops/migrations/0006_auto_20190318_1023.py b/apps/ops/migrations/0006_auto_20190318_1023.py deleted file mode 100644 index f0d88081a..000000000 --- a/apps/ops/migrations/0006_auto_20190318_1023.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-03-18 02:23 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0005_auto_20181219_1807'), - ] - - operations = [ - migrations.AlterField( - model_name='adhoc', - name='run_as', - field=models.CharField(default='', max_length=64, null=True, verbose_name='Username'), - ), - ] diff --git a/apps/ops/migrations/0007_auto_20190724_2002.py b/apps/ops/migrations/0007_auto_20190724_2002.py deleted file mode 100644 index d0303aaa0..000000000 --- a/apps/ops/migrations/0007_auto_20190724_2002.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-24 12:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0006_auto_20190318_1023'), - ] - - operations = [ - migrations.AlterField( - model_name='adhoc', - name='_become', - field=models.CharField(blank=True, default='', max_length=1024, verbose_name='Become'), - ), - migrations.AlterField( - model_name='adhoc', - name='created_by', - field=models.CharField(blank=True, default='', max_length=64, null=True, verbose_name='Create by'), - ), - migrations.AlterField( - model_name='adhoc', - name='run_as', - field=models.CharField(blank=True, default='', max_length=64, null=True, verbose_name='Username'), - ), - ] diff --git a/apps/ops/migrations/0008_auto_20190919_2100.py b/apps/ops/migrations/0008_auto_20190919_2100.py deleted file mode 100644 index c804276dd..000000000 --- a/apps/ops/migrations/0008_auto_20190919_2100.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-19 13:00 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0007_auto_20190724_2002'), - ] - - operations = [ - migrations.AddField( - model_name='task', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AlterField( - model_name='task', - name='date_created', - field=models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Date created'), - ), - migrations.AlterModelOptions( - name='task', - options={'get_latest_by': 'date_created', - 'ordering': ('-date_updated',)}, - ), - ] diff --git a/apps/ops/migrations/0009_auto_20191217_1713.py b/apps/ops/migrations/0009_auto_20191217_1713.py deleted file mode 100644 index 75ba632d8..000000000 --- a/apps/ops/migrations/0009_auto_20191217_1713.py +++ /dev/null @@ -1,72 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-17 09:13 - -from django.db import migrations, models -import django.db.models.deletion -from django.core.exceptions import ObjectDoesNotExist - - -def migrate_task_data(apps, schema_editor): - task_model = apps.get_model("ops", "Task") - db_alias = schema_editor.connection.alias - tasks = task_model.objects.using(db_alias).all() - for task in tasks: - try: - latest_history = task.history.latest() - except ObjectDoesNotExist: - latest_history = None - try: - latest_adhoc = task.adhoc.latest() - except ObjectDoesNotExist: - latest_adhoc = None - if latest_history and latest_history.adhoc: - latest_history.hosts_amount = latest_history.adhoc.hosts.count() - latest_history.save() - total_run_amount = task.history.all().count() - success_run_amount = task.history.filter(is_success=True).count() - task.latest_history = latest_history - task.latest_adhoc = latest_adhoc - task.total_run_amount = total_run_amount - task.success_run_amount = success_run_amount - task.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0008_auto_20190919_2100'), - ] - - operations = [ - migrations.AddField( - model_name='task', - name='latest_adhoc', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='task_latest', to='ops.AdHoc'), - ), - migrations.AddField( - model_name='task', - name='latest_history', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='task_latest', to='ops.AdHocRunHistory'), - ), - migrations.AddField( - model_name='task', - name='success_run_amount', - field=models.IntegerField(default=0), - ), - migrations.AddField( - model_name='task', - name='total_run_amount', - field=models.IntegerField(default=0), - ), - migrations.AddField( - model_name='adhocrunhistory', - name='hosts_amount', - field=models.IntegerField(default=0, verbose_name='Host amount'), - ), - migrations.AddField( - model_name='adhocrunhistory', - name='task_display', - field=models.CharField(blank=True, default='', max_length=128, - verbose_name='Task display'), - ), - migrations.RunPython(migrate_task_data), - ] diff --git a/apps/ops/migrations/0010_auto_20191217_1758.py b/apps/ops/migrations/0010_auto_20191217_1758.py deleted file mode 100644 index af4441ff9..000000000 --- a/apps/ops/migrations/0010_auto_20191217_1758.py +++ /dev/null @@ -1,68 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-17 09:58 - -import common.db.fields -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0009_auto_20191217_1713'), - ] - - operations = [ - migrations.RemoveField( - model_name='adhoc', - name='_hosts', - ), - migrations.AlterField( - model_name='adhoc', - name='_become', - field=common.db.fields.EncryptJsonDictCharField(blank=True, null=True, default='', max_length=1024, verbose_name='Become'), - ), - migrations.AlterField( - model_name='adhoc', - name='_options', - field=common.db.fields.JsonDictCharField(default='', max_length=1024, verbose_name='Options'), - ), - migrations.AlterField( - model_name='adhoc', - name='_tasks', - field=common.db.fields.JsonListTextField(verbose_name='Tasks'), - ), - migrations.RenameField( - model_name='adhoc', - old_name='_become', - new_name='become', - ), - migrations.RenameField( - model_name='adhoc', - old_name='_options', - new_name='options', - ), - migrations.RenameField( - model_name='adhoc', - old_name='_tasks', - new_name='tasks', - ), - migrations.AlterField( - model_name='adhocrunhistory', - name='_result', - field=common.db.fields.JsonDictTextField(blank=True, null=True, verbose_name='Adhoc raw result'), - ), - migrations.AlterField( - model_name='adhocrunhistory', - name='_summary', - field=common.db.fields.JsonDictTextField(blank=True, null=True, verbose_name='Adhoc result summary'), - ), - migrations.RenameField( - model_name='adhocrunhistory', - old_name='_result', - new_name='result', - ), - migrations.RenameField( - model_name='adhocrunhistory', - old_name='_summary', - new_name='summary', - ), - ] diff --git a/apps/ops/migrations/0011_auto_20200106_1534.py b/apps/ops/migrations/0011_auto_20200106_1534.py deleted file mode 100644 index 2938c502e..000000000 --- a/apps/ops/migrations/0011_auto_20200106_1534.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2.7 on 2020-01-06 07:34 - -import common.db.fields -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0010_auto_20191217_1758'), - ] - - operations = [ - migrations.AlterField( - model_name='adhoc', - name='become', - field=common.db.fields.EncryptJsonDictCharField(blank=True, default='', max_length=1024, null=True, verbose_name='Become'), - ), - ] diff --git a/apps/ops/migrations/0012_auto_20200108_1659.py b/apps/ops/migrations/0012_auto_20200108_1659.py deleted file mode 100644 index d12bf4576..000000000 --- a/apps/ops/migrations/0012_auto_20200108_1659.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 2.2.7 on 2020-01-08 08:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0011_auto_20200106_1534'), - ] - - operations = [ - migrations.RenameField( - model_name='task', - old_name='created_by', - new_name='org_id', - ), - migrations.AlterUniqueTogether( - name='task', - unique_together={('name', 'org_id')}, - ), - ] diff --git a/apps/ops/migrations/0013_auto_20200108_1706.py b/apps/ops/migrations/0013_auto_20200108_1706.py deleted file mode 100644 index e6ce99562..000000000 --- a/apps/ops/migrations/0013_auto_20200108_1706.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.2.7 on 2020-01-08 09:06 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0012_auto_20200108_1659'), - ] - - operations = [ - migrations.AddField( - model_name='adhoc', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AddField( - model_name='adhocrunhistory', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='task', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - ] diff --git a/apps/ops/migrations/0014_auto_20200108_1749.py b/apps/ops/migrations/0014_auto_20200108_1749.py deleted file mode 100644 index a9b184e5c..000000000 --- a/apps/ops/migrations/0014_auto_20200108_1749.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.2.7 on 2020-01-08 09:49 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0013_auto_20200108_1706'), - ] - - operations = [ - migrations.RenameModel( - old_name='AdHocRunHistory', - new_name='AdHocExecution', - ), - ] diff --git a/apps/ops/migrations/0015_auto_20200108_1809.py b/apps/ops/migrations/0015_auto_20200108_1809.py deleted file mode 100644 index 200d9b7e4..000000000 --- a/apps/ops/migrations/0015_auto_20200108_1809.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 2.2.7 on 2020-01-08 10:09 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0014_auto_20200108_1749'), - ] - - operations = [ - migrations.RenameField( - model_name='task', - old_name='latest_history', - new_name='latest_execution', - ), - migrations.AlterField( - model_name='adhocexecution', - name='adhoc', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='execution', to='ops.AdHoc'), - ), - migrations.AlterField( - model_name='adhocexecution', - name='task', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='execution', to='ops.Task'), - ), - migrations.AlterModelTable( - name='adhocexecution', - table='ops_adhoc_execution', - ), - ] diff --git a/apps/ops/migrations/0016_commandexecution_org_id.py b/apps/ops/migrations/0016_commandexecution_org_id.py deleted file mode 100644 index f034a4f90..000000000 --- a/apps/ops/migrations/0016_commandexecution_org_id.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-02-27 09:51 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0015_auto_20200108_1809'), - ] - - operations = [ - migrations.AddField( - model_name='commandexecution', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - ] diff --git a/apps/ops/migrations/0017_auto_20200306_1747.py b/apps/ops/migrations/0017_auto_20200306_1747.py deleted file mode 100644 index efcea5d4d..000000000 --- a/apps/ops/migrations/0017_auto_20200306_1747.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.10 on 2020-03-06 09:47 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0016_commandexecution_org_id'), - ] - - operations = [ - migrations.AlterField( - model_name='task', - name='crontab', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab'), - ), - migrations.AlterField( - model_name='task', - name='interval', - field=models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval'), - ), - ] diff --git a/apps/ops/migrations/0018_auto_20200509_1434.py b/apps/ops/migrations/0018_auto_20200509_1434.py deleted file mode 100644 index 5bbf87610..000000000 --- a/apps/ops/migrations/0018_auto_20200509_1434.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 2.2.10 on 2020-05-09 06:34 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0017_auto_20200306_1747'), - ] - - operations = [ - migrations.AlterField( - model_name='commandexecution', - name='date_created', - field=models.DateTimeField(auto_now_add=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='commandexecution', - name='date_finished', - field=models.DateTimeField(null=True, verbose_name='Date finished'), - ), - migrations.AlterField( - model_name='commandexecution', - name='date_start', - field=models.DateTimeField(null=True, verbose_name='Date start'), - ), - migrations.AlterField( - model_name='commandexecution', - name='is_finished', - field=models.BooleanField(default=False, verbose_name='Is finished'), - ), - ] diff --git a/apps/ops/migrations/0019_adhocexecution_celery_task_id.py b/apps/ops/migrations/0019_adhocexecution_celery_task_id.py deleted file mode 100644 index 4789267e6..000000000 --- a/apps/ops/migrations/0019_adhocexecution_celery_task_id.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2020-12-30 12:04 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0018_auto_20200509_1434'), - ] - - operations = [ - migrations.AddField( - model_name='adhocexecution', - name='celery_task_id', - field=models.UUIDField(default=None, null=True), - ), - ] diff --git a/apps/ops/migrations/0020_adhoc_run_system_user.py b/apps/ops/migrations/0020_adhoc_run_system_user.py deleted file mode 100644 index 2b9815cd6..000000000 --- a/apps/ops/migrations/0020_adhoc_run_system_user.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 3.1.6 on 2021-07-14 08:44 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0076_delete_assetuser'), - ('ops', '0019_adhocexecution_celery_task_id'), - ] - - operations = [ - migrations.AddField( - model_name='adhoc', - name='run_system_user', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='assets.systemuser'), - ), - ] diff --git a/apps/ops/migrations/0021_auto_20211130_1037.py b/apps/ops/migrations/0021_auto_20211130_1037.py deleted file mode 100644 index 362abe030..000000000 --- a/apps/ops/migrations/0021_auto_20211130_1037.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.1.13 on 2021-11-30 02:37 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0020_adhoc_run_system_user'), - ] - - operations = [ - migrations.AlterModelOptions( - name='adhoc', - options={'get_latest_by': 'date_created', 'verbose_name': 'AdHoc'}, - ), - migrations.AlterModelOptions( - name='adhocexecution', - options={'get_latest_by': 'date_start', 'verbose_name': 'AdHoc execution'}, - ), - migrations.AlterModelOptions( - name='commandexecution', - options={'verbose_name': 'Command execution'}, - ), - migrations.AlterModelOptions( - name='task', - options={'get_latest_by': 'date_created', 'ordering': ('-date_updated',), 'verbose_name': 'Task'}, - ), - migrations.AlterModelOptions( - name='task', - options={'get_latest_by': 'date_created', 'ordering': ('-date_updated',), 'permissions': [('view_taskmonitor', 'Can view task monitor')], 'verbose_name': 'Task'}, - ), - ] diff --git a/apps/ops/migrations/0022_auto_20220817_1346.py b/apps/ops/migrations/0022_auto_20220817_1346.py deleted file mode 100644 index 2e1c8be47..000000000 --- a/apps/ops/migrations/0022_auto_20220817_1346.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-17 05:46 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('ops', '0021_auto_20211130_1037'), - ] - - operations = [ - migrations.RemoveField( - model_name='adhocexecution', - name='adhoc', - ), - migrations.RemoveField( - model_name='adhocexecution', - name='task', - ), - migrations.RemoveField( - model_name='commandexecution', - name='hosts', - ), - migrations.RemoveField( - model_name='commandexecution', - name='user', - ), - migrations.AlterUniqueTogether( - name='task', - unique_together=None, - ), - migrations.RemoveField( - model_name='task', - name='latest_adhoc', - ), - migrations.RemoveField( - model_name='task', - name='latest_execution', - ), - migrations.DeleteModel( - name='AdHoc', - ), - migrations.DeleteModel( - name='AdHocExecution', - ), - migrations.DeleteModel( - name='CommandExecution', - ), - migrations.DeleteModel( - name='Task', - ), - migrations.DeleteModel('CeleryTask'), - ] diff --git a/apps/ops/migrations/0023_auto_20220912_0021.py b/apps/ops/migrations/0023_auto_20220912_0021.py deleted file mode 100644 index 15af282fe..000000000 --- a/apps/ops/migrations/0023_auto_20220912_0021.py +++ /dev/null @@ -1,263 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-28 10:03 - -import uuid - -import django.db.models.deletion -import private_storage.fields -import private_storage.storage.files -import simple_history.models -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - initial = True - - dependencies = [ - ('assets', '0105_auto_20221220_1956'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('ops', '0022_auto_20220817_1346'), - ] - - operations = [ - migrations.CreateModel( - name='CeleryTask', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=1024, verbose_name='Name')), - ('date_last_publish', models.DateTimeField(null=True, verbose_name='Date last publish')), - ], - options={ - 'verbose_name': 'Celery Task', - 'ordering': ('name',), - 'permissions': [('view_taskmonitor', 'Can view task monitor')], - }, - ), - migrations.CreateModel( - name='CeleryTaskExecution', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=1024)), - ('args', models.JSONField(verbose_name='Args')), - ('kwargs', models.JSONField(verbose_name='Kwargs')), - ('state', models.CharField(max_length=16, verbose_name='State')), - ('is_finished', models.BooleanField(default=False, verbose_name='Finished')), - ('date_published', models.DateTimeField(auto_now_add=True, verbose_name='Date published')), - ('date_start', models.DateTimeField(null=True, verbose_name='Date start')), - ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), - ], - options={ - 'verbose_name': 'Celery Task Execution', - }, - ), - migrations.CreateModel( - name='Job', - 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')), - ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')), - ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')), - ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')), - ('name', models.CharField(max_length=128, null=True, verbose_name='Name')), - ('instant', models.BooleanField(default=False)), - ('args', models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Args')), - ('module', - models.CharField(choices=[('shell', 'Shell'), ('win_shell', 'Powershell'), ('python', 'Python')], - default='shell', max_length=128, null=True, verbose_name='Module')), - ('chdir', models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Chdir')), - ('timeout', models.IntegerField(default=-1, verbose_name='Timeout (Seconds)')), - ('type', models.CharField( - choices=[('adhoc', 'Adhoc'), ('playbook', 'Playbook'), ('upload_file', 'Upload File')], - default='adhoc', max_length=128, verbose_name='Type')), - ('runas', models.CharField(default='root', max_length=128, verbose_name='Runas')), - ('runas_policy', models.CharField( - choices=[('privileged_only', 'Privileged Only'), ('privileged_first', 'Privileged First'), - ('skip', 'Skip')], default='skip', max_length=128, verbose_name='Runas policy')), - ('use_parameter_define', models.BooleanField(default=False, verbose_name='Use Parameter Define')), - ('parameters_define', models.JSONField(default=dict, verbose_name='Parameters define')), - ('comment', - models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Comment')), - ('version', models.IntegerField(default=0)), - ('assets', models.ManyToManyField(to='assets.Asset', verbose_name='Assets')), - ('creator', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, - verbose_name='Creator')), - ], - options={ - 'verbose_name': 'Job', - 'ordering': ['date_created'], - }, - ), - migrations.CreateModel( - name='Playbook', - 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')), - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, null=True, verbose_name='Name')), - ('path', private_storage.fields.PrivateFileField(storage=private_storage.storage.files.PrivateFileSystemStorage(), upload_to='playbooks/')), - ('comment', - models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Comment')), - ('creator', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, - verbose_name='Creator')), - ], - options={ - 'abstract': False, - 'ordering': ['date_created'] - }, - ), - migrations.CreateModel( - name='JobExecution', - 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_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('task_id', models.UUIDField(null=True)), - ('status', models.CharField(default='running', max_length=16, verbose_name='Status')), - ('job_version', models.IntegerField(default=0)), - ('parameters', models.JSONField(default=dict, verbose_name='Parameters')), - ('result', models.JSONField(blank=True, null=True, verbose_name='Result')), - ('summary', models.JSONField(default=dict, verbose_name='Summary')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')), - ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), - ('creator', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, - verbose_name='Creator')), - ('job', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='executions', - to='ops.job')), - ], - options={ - 'verbose_name': 'Job Execution', - 'ordering': ['-date_created'], - }, - ), - migrations.AddField( - model_name='job', - name='playbook', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='ops.playbook', - verbose_name='Playbook'), - ), - migrations.CreateModel( - name='HistoricalJob', - 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(blank=True, editable=False, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(blank=True, editable=False, verbose_name='Date updated')), - ('id', models.UUIDField(db_index=True, default=uuid.uuid4)), - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('is_periodic', models.BooleanField(default=False, verbose_name='Periodic run')), - ('interval', models.IntegerField(blank=True, default=24, null=True, verbose_name='Interval')), - ('crontab', models.CharField(blank=True, max_length=128, null=True, verbose_name='Crontab')), - ('name', models.CharField(max_length=128, null=True, verbose_name='Name')), - ('instant', models.BooleanField(default=False)), - ('args', models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Args')), - ('module', - models.CharField(choices=[('shell', 'Shell'), ('win_shell', 'Powershell'), ('python', 'Python')], - default='shell', max_length=128, null=True, verbose_name='Module')), - ('chdir', models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Chdir')), - ('timeout', models.IntegerField(default=-1, verbose_name='Timeout (Seconds)')), - ('type', models.CharField( - choices=[('adhoc', 'Adhoc'), ('playbook', 'Playbook'), ('upload_file', 'Upload File')], - default='adhoc', max_length=128, verbose_name='Type')), - ('runas', models.CharField(default='root', max_length=128, verbose_name='Runas')), - ('runas_policy', models.CharField( - choices=[('privileged_only', 'Privileged Only'), ('privileged_first', 'Privileged First'), - ('skip', 'Skip')], default='skip', max_length=128, verbose_name='Runas policy')), - ('use_parameter_define', models.BooleanField(default=False, verbose_name='Use Parameter Define')), - ('parameters_define', models.JSONField(default=dict, verbose_name='Parameters define')), - ('comment', - models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Comment')), - ('version', models.IntegerField(default=0)), - ('history_id', models.AutoField(primary_key=True, serialize=False)), - ('history_date', models.DateTimeField(db_index=True)), - ('history_change_reason', models.CharField(max_length=100, null=True)), - ('history_type', - models.CharField(choices=[('+', 'Created'), ('~', 'Changed'), ('-', 'Deleted')], max_length=1)), - ('creator', models.ForeignKey(blank=True, db_constraint=False, null=True, - on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', - to=settings.AUTH_USER_MODEL, verbose_name='Creator')), - ('history_user', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', - to=settings.AUTH_USER_MODEL)), - ('playbook', models.ForeignKey(blank=True, db_constraint=False, null=True, - on_delete=django.db.models.deletion.DO_NOTHING, related_name='+', - to='ops.playbook', verbose_name='Playbook')), - ], - options={ - 'verbose_name': 'historical Job', - 'verbose_name_plural': 'historical Jobs', - 'ordering': ('-history_date', '-history_id'), - 'get_latest_by': ('history_date', 'history_id'), - }, - bases=(simple_history.models.HistoricalChanges, models.Model), - ), - migrations.CreateModel( - name='AdHoc', - 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')), - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('pattern', models.CharField(default='all', max_length=1024, verbose_name='Pattern')), - ('module', - models.CharField(choices=[('shell', 'Shell'), ('win_shell', 'Powershell'), ('python', 'Python')], - default='shell', max_length=128, verbose_name='Module')), - ('args', models.CharField(default='', max_length=1024, verbose_name='Args')), - ('comment', - models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Comment')), - ('creator', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, - verbose_name='Creator')), - ], - options={ - 'verbose_name': 'Adhoc', - }, - ), - migrations.CreateModel( - name='JobAuditLog', - fields=[ - ], - options={ - 'verbose_name': 'Job audit log', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('ops.jobexecution',), - ), - migrations.AlterUniqueTogether( - name='adhoc', - unique_together={('name', 'org_id', 'creator')}, - ), - migrations.AlterUniqueTogether( - name='job', - unique_together={('name', 'org_id', 'creator')}, - ), - migrations.AlterUniqueTogether( - name='playbook', - unique_together={('name', 'org_id', 'creator')}, - ), - ] diff --git a/apps/ops/migrations/0024_alter_celerytask_date_last_publish.py b/apps/ops/migrations/0024_alter_celerytask_date_last_publish.py deleted file mode 100644 index 3b7192f60..000000000 --- a/apps/ops/migrations/0024_alter_celerytask_date_last_publish.py +++ /dev/null @@ -1,72 +0,0 @@ -# Generated by Django 3.2.16 on 2022-12-30 08:08 - -import django.db.models -from django.db import migrations, models - - -def compatible(apps, schema_editor): - """ - 兼容旧版本的数据 - """ - model = apps.get_model("ops", "JobExecution") - for obj in model.objects.all(): - if obj.job: - if obj.job.type == 'adhoc': - obj.material = "{}:{}".format(obj.job.module, obj.job.args) - if obj.job.type == 'playbook': - obj.material = "{}:{}:{}".format(obj.job.org.name, obj.job.creator.name, obj.job.playbook.name) - obj.job_type = obj.job.type - obj.save() - else: - obj.delete() - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0023_auto_20220912_0021'), - ] - - operations = [ - migrations.AlterField( - model_name='celerytask', - name='date_last_publish', - field=models.DateTimeField(null=True, verbose_name='Date last publish'), - ), - migrations.AlterField( - model_name='celerytaskexecution', - name='name', - field=models.CharField(max_length=1024, verbose_name='Name'), - ), - migrations.AddField( - model_name='playbook', - name='create_method', - field=models.CharField(choices=[('blank', 'Blank'), ('vcs', 'VCS')], default='blank', max_length=128, verbose_name='CreateMethod'), - ), - migrations.AddField( - model_name='playbook', - name='vcs_url', - field=models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='VCS URL'), - ), - migrations.AlterField( - model_name='jobexecution', - name='job', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='executions', to='ops.job'), - ), - migrations.AddField( - model_name='jobexecution', - name='job_type', - field=models.CharField( - choices=[('adhoc', 'Adhoc'), ('playbook', 'Playbook'), ('upload_file', 'Upload File')], - default='adhoc', max_length=128, verbose_name='Material Type'), - ), - migrations.AddField( - model_name='jobexecution', - name='material', - field=models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='Material'), - ), - migrations.DeleteModel( - name='JobAuditLog', - ), - migrations.RunPython(compatible), - ] diff --git a/apps/ops/migrations/0025_auto_20230413_1531.py b/apps/ops/migrations/0025_auto_20230413_1531.py deleted file mode 100644 index 0b77f1281..000000000 --- a/apps/ops/migrations/0025_auto_20230413_1531.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-13 07:31 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0024_alter_celerytask_date_last_publish'), - ] - - operations = [ - migrations.AlterField( - model_name='adhoc', - name='args', - field=models.CharField(default='', max_length=8192, verbose_name='Args'), - ), - migrations.AlterField( - model_name='historicaljob', - name='args', - field=models.CharField(blank=True, default='', max_length=8192, null=True, verbose_name='Args'), - ), - migrations.AlterField( - model_name='job', - name='args', - field=models.CharField(blank=True, default='', max_length=8192, null=True, verbose_name='Args'), - ), - migrations.AlterField( - model_name='jobexecution', - name='material', - field=models.CharField(blank=True, default='', max_length=8192, null=True, verbose_name='Material'), - ), - ] diff --git a/apps/ops/migrations/0026_auto_20230810_1039.py b/apps/ops/migrations/0026_auto_20230810_1039.py deleted file mode 100644 index 944a61e6e..000000000 --- a/apps/ops/migrations/0026_auto_20230810_1039.py +++ /dev/null @@ -1,48 +0,0 @@ -# Generated by Django 4.1.10 on 2023-08-10 02:36 - -from django.db import migrations, models - -import common.db.encoder - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0025_auto_20230413_1531'), - ] - - operations = [ - migrations.AlterField( - model_name='adhoc', - name='module', - field=models.CharField(choices=[('shell', 'Shell'), ('win_shell', 'Powershell'), ('python', 'Python'), ('mysql', 'MySQL'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('raw', 'Raw')], default='shell', max_length=128, verbose_name='Module'), - ), - migrations.AlterField( - model_name='historicaljob', - name='module', - field=models.CharField(choices=[('shell', 'Shell'), ('win_shell', 'Powershell'), ('python', 'Python'), ('mysql', 'MySQL'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('raw', 'Raw'), ('huawei', 'HUAWEI')], default='shell', max_length=128, null=True, verbose_name='Module'), - ), - migrations.AlterField( - model_name='job', - name='module', - field=models.CharField(choices=[('shell', 'Shell'), ('win_shell', 'Powershell'), ('python', 'Python'), ('mysql', 'MySQL'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('raw', 'Raw'), ('huawei', 'HUAWEI')], default='shell', max_length=128, null=True, verbose_name='Module'), - ), - migrations.AlterField( - model_name='jobexecution', - name='result', - field=models.JSONField(blank=True, encoder=common.db.encoder.ModelJSONFieldEncoder, null=True, verbose_name='Result'), - ), - migrations.AlterField( - model_name='jobexecution', - name='summary', - field=models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, verbose_name='Summary'), - ), - migrations.AlterField( - model_name='adhoc', - name='module', - field=models.CharField( - choices=[('shell', 'Shell'), ('win_shell', 'Powershell'), ('python', 'Python'), ('mysql', 'MySQL'), - ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), - ('oracle', 'Oracle'), ('raw', 'Raw')], default='shell', max_length=128, verbose_name='Module'), - ), - ] diff --git a/apps/ops/migrations/0027_alter_celerytaskexecution_options.py b/apps/ops/migrations/0027_alter_celerytaskexecution_options.py deleted file mode 100644 index 0b3e07308..000000000 --- a/apps/ops/migrations/0027_alter_celerytaskexecution_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-22 06:52 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('ops', '0026_auto_20230810_1039'), - ] - - operations = [ - migrations.AlterModelOptions( - name='celerytaskexecution', - options={'ordering': ['-date_start'], 'verbose_name': 'Celery Task Execution'}, - ), - ] diff --git a/apps/ops/migrations/0028_celerytaskexecution_creator.py b/apps/ops/migrations/0028_celerytaskexecution_creator.py deleted file mode 100644 index 37d44077b..000000000 --- a/apps/ops/migrations/0028_celerytaskexecution_creator.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.1.13 on 2024-03-18 06:47 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('ops', '0027_alter_celerytaskexecution_options'), - ] - - operations = [ - migrations.AddField( - model_name='celerytaskexecution', - name='creator', - field=models.ForeignKey(db_constraint=False, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Creator'), - ), - ] diff --git a/apps/orgs/migrations/0001_initial.py b/apps/orgs/migrations/0001_initial.py index a4705e719..2454a5bae 100644 --- a/apps/orgs/migrations/0001_initial.py +++ b/apps/orgs/migrations/0001_initial.py @@ -1,29 +1,56 @@ -# Generated by Django 2.0.7 on 2018-08-07 03:16 +# Generated by Django 4.1.13 on 2024-05-09 03:16 +from django.db import migrations, models +import orgs.models import uuid -from django.conf import settings -from django.db import migrations, models +default_id = '00000000-0000-0000-0000-000000000002' + + +def add_default_org(apps, schema_editor): + org_cls = apps.get_model('orgs', 'Organization') + defaults = {'name': 'Default', 'id': default_id} + org_cls.objects.get_or_create(defaults=defaults, id=default_id) + + +def update_builtin_org(apps, schema_editor): + org_model = apps.get_model('orgs', 'Organization') + org_model.objects.create( + id='00000000-0000-0000-0000-000000000004', + name='SYSTEM', builtin=True + ) + + # 更新 Default + org_model.objects.filter(name='DEFAULT').update(builtin=True) + class Migration(migrations.Migration): + initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( name='Organization', 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('admins', models.ManyToManyField(blank=True, related_name='admin_orgs', to=settings.AUTH_USER_MODEL)), - ('users', models.ManyToManyField(blank=True, related_name='orgs', to=settings.AUTH_USER_MODEL)), + ('builtin', models.BooleanField(default=False, verbose_name='Builtin')), ], + options={ + 'verbose_name': 'Organization', + 'permissions': (('view_rootorg', 'Can view root org'), ('view_alljoinedorg', 'Can view all joined org')), + }, + bases=(orgs.models.OrgRoleMixin, models.Model), ), + migrations.RunPython(add_default_org), + migrations.RunPython(update_builtin_org), ] diff --git a/apps/orgs/migrations/0002_auto_20180903_1132.py b/apps/orgs/migrations/0002_auto_20180903_1132.py index c73f2e7fd..83bdf2522 100644 --- a/apps/orgs/migrations/0002_auto_20180903_1132.py +++ b/apps/orgs/migrations/0002_auto_20180903_1132.py @@ -1,17 +1,23 @@ -# Generated by Django 2.1 on 2018-09-03 03:32 +# Generated by Django 4.1.13 on 2024-05-09 03:16 -from django.db import migrations +from django.conf import settings +from django.db import migrations, models class Migration(migrations.Migration): + initial = True + dependencies = [ ('orgs', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('rbac', '0001_initial'), ] operations = [ - migrations.AlterModelOptions( - name='organization', - options={'verbose_name': 'Organization'}, + migrations.AddField( + model_name='organization', + name='members', + field=models.ManyToManyField(related_name='orgs', through='rbac.RoleBinding', to=settings.AUTH_USER_MODEL), ), ] diff --git a/apps/orgs/migrations/0003_auto_20190916_1057.py b/apps/orgs/migrations/0003_auto_20190916_1057.py deleted file mode 100644 index d8be6dee5..000000000 --- a/apps/orgs/migrations/0003_auto_20190916_1057.py +++ /dev/null @@ -1,30 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-16 02:57 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('orgs', '0002_auto_20180903_1132'), - ] - - operations = [ - migrations.AddField( - model_name='organization', - name='auditors', - field=models.ManyToManyField(blank=True, related_name='related_audit_orgs', to=settings.AUTH_USER_MODEL), - ), - migrations.AlterField( - model_name='organization', - name='admins', - field=models.ManyToManyField(blank=True, related_name='related_admin_orgs', to=settings.AUTH_USER_MODEL), - ), - migrations.AlterField( - model_name='organization', - name='users', - field=models.ManyToManyField(blank=True, related_name='related_user_orgs', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/apps/orgs/migrations/0004_organizationmember.py b/apps/orgs/migrations/0004_organizationmember.py deleted file mode 100644 index 6b43a5850..000000000 --- a/apps/orgs/migrations/0004_organizationmember.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-21 11:27 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('orgs', '0003_auto_20190916_1057'), - ] - - operations = [ - migrations.CreateModel( - name='OrganizationMember', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('role', models.CharField(choices=[('Admin', 'Administrator'), ('User', 'User'), ('Auditor', 'Auditor')], default='User', max_length=16, verbose_name='Role')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('created_by', models.CharField(max_length=128, null=True, verbose_name='Created by')), - ('org', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='m2m_org_members', to='orgs.Organization', verbose_name='Organization')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='m2m_org_members', to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'db_table': 'orgs_organization_members', - 'unique_together': {('org', 'user', 'role')}, - }, - ), - ] diff --git a/apps/orgs/migrations/0005_auto_20200721_1937.py b/apps/orgs/migrations/0005_auto_20200721_1937.py deleted file mode 100644 index ac0ec8a08..000000000 --- a/apps/orgs/migrations/0005_auto_20200721_1937.py +++ /dev/null @@ -1,35 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-21 11:37 - -from django.db import migrations - - -def migrate_old_organization_members(apps, schema_editor): - org_model = apps.get_model("orgs", "Organization") - org_member_model = apps.get_model('orgs', 'OrganizationMember') - orgs = org_model.objects.all() - - roles = ['User', 'Auditor', 'Admin'] - - for org in orgs: - users = org.users.all().only('id') - auditors = org.auditors.all().only('id') - admins = org.admins.all().only('id') - total_members = zip([users, auditors, admins], roles) - - org_members = [] - for members, role in total_members: - for user in members: - org_user = org_member_model(user=user, org=org, role=role) - org_members.append(org_user) - org_member_model.objects.bulk_create(org_members) - - -class Migration(migrations.Migration): - - dependencies = [ - ('orgs', '0004_organizationmember'), - ] - - operations = [ - migrations.RunPython(migrate_old_organization_members) - ] diff --git a/apps/orgs/migrations/0006_auto_20200721_1937.py b/apps/orgs/migrations/0006_auto_20200721_1937.py deleted file mode 100644 index fe0b1f477..000000000 --- a/apps/orgs/migrations/0006_auto_20200721_1937.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-21 11:37 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('orgs', '0005_auto_20200721_1937'), - ] - - operations = [ - migrations.RemoveField( - model_name='organization', - name='admins', - ), - migrations.RemoveField( - model_name='organization', - name='auditors', - ), - migrations.RemoveField( - model_name='organization', - name='users', - ), - migrations.AddField( - model_name='organization', - name='members', - field=models.ManyToManyField(related_name='orgs', through='orgs.OrganizationMember', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/apps/orgs/migrations/0007_auto_20200728_1805.py b/apps/orgs/migrations/0007_auto_20200728_1805.py deleted file mode 100644 index 6c05e75b2..000000000 --- a/apps/orgs/migrations/0007_auto_20200728_1805.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-28 10:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('orgs', '0006_auto_20200721_1937'), - ] - - operations = [ - migrations.AlterField( - model_name='organizationmember', - name='role', - field=models.CharField(choices=[('Admin', 'Organization administrator'), ('User', 'User'), ('Auditor', 'Organization auditor')], default='User', max_length=16, verbose_name='Role'), - ), - ] diff --git a/apps/orgs/migrations/0008_auto_20200819_2041.py b/apps/orgs/migrations/0008_auto_20200819_2041.py deleted file mode 100644 index 524d29e39..000000000 --- a/apps/orgs/migrations/0008_auto_20200819_2041.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-19 12:41 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('orgs', '0007_auto_20200728_1805'), - ] - - operations = [ - migrations.AlterField( - model_name='organizationmember', - name='role', - field=models.CharField(choices=[('Admin', 'Organization administrator'), ('Auditor', 'Organization auditor'), ('User', 'User')], default='User', max_length=16, verbose_name='Role'), - ), - ] diff --git a/apps/orgs/migrations/0009_auto_20201023_1628.py b/apps/orgs/migrations/0009_auto_20201023_1628.py deleted file mode 100644 index 9cc63f54b..000000000 --- a/apps/orgs/migrations/0009_auto_20201023_1628.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-23 08:28 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('orgs', '0008_auto_20200819_2041'), - ] - - operations = [ - migrations.AlterField( - model_name='organization', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - ] diff --git a/apps/orgs/migrations/0010_auto_20210219_1241.py b/apps/orgs/migrations/0010_auto_20210219_1241.py deleted file mode 100644 index 6fc3b0577..000000000 --- a/apps/orgs/migrations/0010_auto_20210219_1241.py +++ /dev/null @@ -1,86 +0,0 @@ -# Generated by Django 3.1 on 2021-02-19 04:41 - -import time -import sys - -from django.db import migrations - - -default_id = '00000000-0000-0000-0000-000000000002' - - -def add_default_org(apps, schema_editor): - org_cls = apps.get_model('orgs', 'Organization') - defaults = {'name': 'Default', 'id': default_id} - org_cls.objects.get_or_create(defaults=defaults, id=default_id) - - -def migrate_default_org_id(apps, schema_editor): - org_app_models = [ - ('applications', ['Application']), - ('assets', [ - 'AdminUser', 'Asset', 'AuthBook', 'CommandFilter', - 'CommandFilterRule', 'Domain', 'Gateway', 'GatheredUser', - 'Label', 'Node', 'SystemUser' - ]), - ('audits', ['FTPLog', 'OperateLog']), - ('ops', ['AdHoc', 'AdHocExecution', 'CommandExecution', 'Task']), - ('perms', ['ApplicationPermission', 'AssetPermission', 'UserAssetGrantedTreeNodeRelation']), - ('terminal', ['Session', 'Command']), - ('tickets', ['Ticket']), - ('users', ['UserGroup']), - ] - print("") - for app, models_name in org_app_models: - for model_name in models_name: - t_start = time.time() - print("\tMigrate model org id: {}".format(model_name), end='') - sys.stdout.flush() - - model_cls = apps.get_model(app, model_name) - model_cls.objects.filter(org_id='').update(org_id=default_id) - interval = round((time.time() - t_start) * 1000, 2) - print("\tdone, use {} ms".format(interval)) - - -def add_all_user_to_default_org(apps, schema_editor): - user_model = apps.get_model('users', 'User') - org_model = apps.get_model('orgs', 'Organization') - org_members_model = apps.get_model('orgs', 'OrganizationMember') - - users_qs = user_model.objects.all() - default_org = org_model.objects.get(id=default_id) - - t_start = time.time() - count = users_qs.count() - print(f'\tWill add users to default org: {count}') - - batch_size = 1000 - for i in range(0, count, batch_size): - users = list(users_qs[i:i + batch_size]) - members = [org_members_model(user=user, org=default_org) for user in users] - org_members_model.objects.bulk_create(members, ignore_conflicts=True) - print(f'\t Add users to default org: {i+1}-{i+len(users)}') - interval = round((time.time() - t_start) * 1000, 2) - print(f'\tdone, use {interval} ms') - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0007_auto_20201224_1821'), - ('audits', '0011_userloginlog_backend'), - ('ops', '0019_adhocexecution_celery_task_id'), - ('perms', '0018_auto_20210208_1515'), - ('applications', '0008_auto_20210104_0435'), - ('terminal', '0031_auto_20210113_1356'), - ('users', '0031_auto_20201118_1801'), - ('assets', '0066_auto_20210208_1802'), - ('orgs', '0009_auto_20201023_1628'), - ] - - operations = [ - migrations.RunPython(add_default_org), - migrations.RunPython(migrate_default_org_id), - migrations.RunPython(add_all_user_to_default_org) - ] diff --git a/apps/orgs/migrations/0011_auto_20211223_1913.py b/apps/orgs/migrations/0011_auto_20211223_1913.py deleted file mode 100644 index 5a1789ed4..000000000 --- a/apps/orgs/migrations/0011_auto_20211223_1913.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-23 11:13 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('orgs', '0010_auto_20210219_1241'), - ] - - operations = [ - migrations.AlterField( - model_name='organizationmember', - name='role', - field=models.CharField(default='User', max_length=16, verbose_name='Role'), - ), - ] diff --git a/apps/orgs/migrations/0012_auto_20220118_1054.py b/apps/orgs/migrations/0012_auto_20220118_1054.py deleted file mode 100644 index a7d21277c..000000000 --- a/apps/orgs/migrations/0012_auto_20220118_1054.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.13 on 2022-01-18 02:54 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('rbac', '0004_auto_20211201_1901'), - ('orgs', '0011_auto_20211223_1913'), - ] - - operations = [ - migrations.AlterModelOptions( - name='organization', - options={'permissions': (('view_rootorg', 'Can view root org'),), 'verbose_name': 'Organization'}, - ), - migrations.AlterField( - model_name='organization', - name='members', - field=models.ManyToManyField(related_name='orgs', through='rbac.RoleBinding', to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/apps/orgs/migrations/0013_alter_organization_options.py b/apps/orgs/migrations/0013_alter_organization_options.py deleted file mode 100644 index e868a87a3..000000000 --- a/apps/orgs/migrations/0013_alter_organization_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.12 on 2022-07-18 05:57 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('orgs', '0012_auto_20220118_1054'), - ] - - operations = [ - migrations.AlterModelOptions( - name='organization', - options={'permissions': (('view_rootorg', 'Can view root org'), ('view_alljoinedorg', 'Can view all joined org')), 'verbose_name': 'Organization'}, - ), - ] diff --git a/apps/orgs/migrations/0014_organization_builtin.py b/apps/orgs/migrations/0014_organization_builtin.py deleted file mode 100644 index a9b407ffc..000000000 --- a/apps/orgs/migrations/0014_organization_builtin.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.2.14 on 2022-10-26 09:07 - -from django.db import migrations, models - - -def update_builtin_org(apps, schema_editor): - org_model = apps.get_model('orgs', 'Organization') - org_model.objects.create( - id='00000000-0000-0000-0000-000000000004', - name='SYSTEM', builtin=True - ) - - # 更新 Default - org_model.objects.filter(name='DEFAULT').update(builtin=True) - - -class Migration(migrations.Migration): - - dependencies = [ - ('orgs', '0013_alter_organization_options'), - ] - - operations = [ - migrations.AddField( - model_name='organization', - name='builtin', - field=models.BooleanField(default=False, verbose_name='Builtin'), - ), - migrations.RunPython(update_builtin_org), - migrations.DeleteModel( - name='OrganizationMember', - ), - ] diff --git a/apps/orgs/migrations/0015_auto_20221220_1956.py b/apps/orgs/migrations/0015_auto_20221220_1956.py deleted file mode 100644 index df92f6862..000000000 --- a/apps/orgs/migrations/0015_auto_20221220_1956.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('orgs', '0014_organization_builtin'), - ] - - operations = [ - migrations.AddField( - model_name='organization', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='organization', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='organization', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - ] diff --git a/apps/perms/migrations/0001_initial.py b/apps/perms/migrations/0001_initial.py index 63605a247..adc3be69e 100644 --- a/apps/perms/migrations/0001_initial.py +++ b/apps/perms/migrations/0001_initial.py @@ -1,9 +1,11 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2017-12-24 15:21 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import common.utils +import assets.models.node +import common.utils.django from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import perms.models.asset_permission import uuid @@ -13,22 +15,90 @@ class Migration(migrations.Migration): dependencies = [ ('assets', '0001_initial'), + ('accounts', '0002_auto_20220616_0021'), ] operations = [ migrations.CreateModel( name='AssetPermission', 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('accounts', models.JSONField(default=list, verbose_name='Account')), + ('protocols', models.JSONField(default=perms.models.asset_permission.default_protocols, verbose_name='Protocols')), + ('actions', models.IntegerField(default=1, verbose_name='Actions')), + ('date_start', models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date start')), + ('date_expired', models.DateTimeField(db_index=True, default=common.utils.django.date_expired_default, verbose_name='Date expired')), ('is_active', models.BooleanField(default=True, verbose_name='Active')), - ('date_expired', models.DateTimeField(default=common.utils.date_expired_default, verbose_name='Date expired')), - ('created_by', models.CharField(blank=True, max_length=128, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('asset_groups', models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.AssetGroup', verbose_name='Asset group')), - ('assets', models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.Asset', verbose_name='Asset')), - ('system_users', models.ManyToManyField(related_name='granted_by_permissions', to='assets.SystemUser', verbose_name='System user')), + ('from_ticket', models.BooleanField(default=False, verbose_name='From ticket')), ], + options={ + 'verbose_name': 'Asset permission', + 'ordering': ('name',), + 'permissions': [], + }, + ), + migrations.CreateModel( + name='PermedAccount', + fields=[ + ], + options={ + 'verbose_name': 'Permed account', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('accounts.account',), + ), + migrations.CreateModel( + name='PermedAsset', + fields=[ + ], + options={ + 'verbose_name': 'Permed asset', + 'permissions': [('view_myassets', 'Can view my assets'), ('view_userassets', 'Can view user assets'), ('view_usergroupassets', 'Can view usergroup assets')], + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('assets.asset',), + ), + migrations.CreateModel( + name='PermNode', + fields=[ + ], + options={ + 'ordering': [], + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('assets.node',), + ), + migrations.CreateModel( + name='UserAssetGrantedTreeNodeRelation', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('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')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('node_key', models.CharField(db_index=True, max_length=64, verbose_name='Key')), + ('node_parent_key', models.CharField(db_index=True, default='', max_length=64, verbose_name='Parent key')), + ('node_from', models.CharField(choices=[('granted', 'Direct node granted'), ('child', 'Have children node'), ('asset', 'Direct asset granted')], db_index=True, max_length=16)), + ('node_assets_amount', models.IntegerField(default=0)), + ('node', models.ForeignKey(db_constraint=False, default=None, on_delete=django.db.models.deletion.CASCADE, related_name='granted_node_rels', to='assets.node')), + ], + options={ + 'abstract': False, + }, + bases=(assets.models.node.FamilyMixin, models.Model), ), ] diff --git a/apps/perms/migrations/0002_auto_20171228_0025.py b/apps/perms/migrations/0002_auto_20171228_0025.py index 23a5dcf78..b958e9c4c 100644 --- a/apps/perms/migrations/0002_auto_20171228_0025.py +++ b/apps/perms/migrations/0002_auto_20171228_0025.py @@ -1,28 +1,49 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2017-12-27 16:25 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 from django.conf import settings from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): + initial = True + dependencies = [ - ('users', '0002_auto_20171225_1157'), + ('assets', '0002_auto_20180105_1807'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('users', '0001_initial'), ('perms', '0001_initial'), ] operations = [ + migrations.AddField( + model_name='userassetgrantedtreenoderelation', + name='user', + field=models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='assetpermission', + name='assets', + field=models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.asset', verbose_name='Asset'), + ), + migrations.AddField( + model_name='assetpermission', + name='nodes', + field=models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.node', verbose_name='Node'), + ), migrations.AddField( model_name='assetpermission', name='user_groups', - field=models.ManyToManyField(blank=True, related_name='asset_permissions', to='users.UserGroup', verbose_name='User group'), + field=models.ManyToManyField(blank=True, related_name='%(class)ss', to='users.usergroup', verbose_name='User group'), ), migrations.AddField( model_name='assetpermission', name='users', - field=models.ManyToManyField(blank=True, related_name='asset_permissions', to=settings.AUTH_USER_MODEL, verbose_name='User'), + field=models.ManyToManyField(blank=True, related_name='%(class)ss', to=settings.AUTH_USER_MODEL, verbose_name='User'), + ), + migrations.AlterUniqueTogether( + name='assetpermission', + unique_together={('org_id', 'name')}, ), ] diff --git a/apps/perms/migrations/0002_auto_20171228_0025_squashed_0009_auto_20180903_1132.py b/apps/perms/migrations/0002_auto_20171228_0025_squashed_0009_auto_20180903_1132.py deleted file mode 100644 index 12d8e70ce..000000000 --- a/apps/perms/migrations/0002_auto_20171228_0025_squashed_0009_auto_20180903_1132.py +++ /dev/null @@ -1,124 +0,0 @@ -# Generated by Django 2.1.7 on 2019-02-28 10:21 - -import common.utils.django -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import django.utils.timezone -import uuid - - -# Functions from the following migrations need manual copying. -# Move them and any dependencies into this file, then update the -# RunPython operations to refer to the local versions: -# perms.migrations.0005_migrate_data_20180411_1144 - -def migrate_node_permissions(apps, schema_editor): - node_perm_model = apps.get_model("perms", "NodePermission") - asset_perm_model = apps.get_model("perms", "AssetPermission") - db_alias = schema_editor.connection.alias - for old in node_perm_model.objects.using(db_alias).all(): - perm = asset_perm_model.objects.using(db_alias).create( - name="{}-{}-{}".format( - old.node.value, - old.user_group.name, - old.system_user.name - ), - is_active=old.is_active, - date_expired=old.date_expired, - created_by=old.date_expired, - date_created=old.date_created, - comment=old.comment, - ) - perm.user_groups.add(old.user_group) - perm.nodes.add(old.node) - perm.system_users.add(old.system_user) - - -def migrate_system_assets_relation(apps, schema_editor): - system_user_model = apps.get_model("assets", "SystemUser") - db_alias = schema_editor.connection.alias - for s in system_user_model.objects.using(db_alias).all(): - nodes = list(s.nodes.all()) - s.nodes.set([]) - s.nodes.set(nodes) - - -class Migration(migrations.Migration): - - replaces = [('perms', '0002_auto_20171228_0025'), ('perms', '0003_auto_20180225_1815'), ('perms', '0004_auto_20180411_1135'), ('perms', '0005_migrate_data_20180411_1144'), ('perms', '0006_auto_20180606_1505'), ('perms', '0007_auto_20180807_1116'), ('perms', '0008_auto_20180816_1652'), ('perms', '0009_auto_20180903_1132')] - - dependencies = [ - ('users', '0002_auto_20171225_1157'), - ('assets', '0007_auto_20180225_1815'), - ('assets', '0013_auto_20180411_1135'), - ('users', '0004_auto_20180125_1218'), - ('perms', '0001_initial'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.AddField( - model_name='assetpermission', - name='user_groups', - field=models.ManyToManyField(blank=True, related_name='asset_permissions', to='users.UserGroup', verbose_name='User group'), - ), - migrations.AddField( - model_name='assetpermission', - name='users', - field=models.ManyToManyField(blank=True, related_name='asset_permissions', to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - migrations.RemoveField( - model_name='assetpermission', - name='asset_groups', - ), - migrations.AddField( - model_name='assetpermission', - name='date_start', - field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date start'), - ), - migrations.AddField( - model_name='assetpermission', - name='nodes', - field=models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.Node', verbose_name='Node'), - ), - # migrations.RunPython( - # code=migrate_node_permissions, - # ), - migrations.RunPython( - code=migrate_system_assets_relation, - ), - migrations.AlterField( - model_name='assetpermission', - name='date_expired', - field=models.DateTimeField(db_index=True, default=common.utils.django.date_expired_default, verbose_name='Date expired'), - ), - migrations.AlterField( - model_name='assetpermission', - name='date_start', - field=models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date start'), - ), - migrations.AddField( - model_name='assetpermission', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AlterField( - model_name='assetpermission', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='assetpermission', - unique_together={('org_id', 'name')}, - ), - migrations.AlterField( - model_name='assetpermission', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterModelOptions( - name='assetpermission', - options={'verbose_name': 'Asset permission'}, - ), - ] diff --git a/apps/perms/migrations/0003_action.py b/apps/perms/migrations/0003_action.py deleted file mode 100644 index c9dea7736..000000000 --- a/apps/perms/migrations/0003_action.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 2.1.7 on 2019-04-12 07:00 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0002_auto_20171228_0025_squashed_0009_auto_20180903_1132'), - ] - - operations = [ - migrations.CreateModel( - name='Action', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(choices=[('all', 'All'), ('connect', 'Connect'), ('upload_file', 'Upload file'), ('download_file', 'Download file')], max_length=128, unique=True, verbose_name='Name')), - ], - options={ - 'verbose_name': 'Action', - }, - ), - ] diff --git a/apps/perms/migrations/0004_assetpermission_actions.py b/apps/perms/migrations/0004_assetpermission_actions.py deleted file mode 100644 index dfe07f317..000000000 --- a/apps/perms/migrations/0004_assetpermission_actions.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-04-12 09:17 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0003_action'), - ] - - operations = [ - migrations.AddField( - model_name='assetpermission', - name='actions', - field=models.ManyToManyField(blank=True, related_name='permissions', to='perms.Action', verbose_name='Action'), - ), - ] diff --git a/apps/perms/migrations/0005_auto_20190521_1619.py b/apps/perms/migrations/0005_auto_20190521_1619.py deleted file mode 100644 index f000b8685..000000000 --- a/apps/perms/migrations/0005_auto_20190521_1619.py +++ /dev/null @@ -1,55 +0,0 @@ -# Generated by Django 2.1.7 on 2019-05-21 08:19 - -import common.utils.django -from django.conf import settings -from django.db import migrations, models -import django.utils.timezone -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0019_auto_20190304_1459'), - ('applications', '0001_initial'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('perms', '0004_assetpermission_actions'), - ] - - operations = [ - migrations.CreateModel( - name='RemoteAppPermission', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), - ('date_start', models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date start')), - ('date_expired', models.DateTimeField(db_index=True, default=common.utils.django.date_expired_default, verbose_name='Date expired')), - ('created_by', models.CharField(blank=True, max_length=128, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('remote_apps', models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='applications.RemoteApp', verbose_name='RemoteApp')), - ('user_groups', models.ManyToManyField(blank=True, to='users.UserGroup', verbose_name='User group')), - ('users', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'verbose_name': 'RemoteApp permission', - 'ordering': ('name',), - }, - ), - migrations.AlterField( - model_name='assetpermission', - name='user_groups', - field=models.ManyToManyField(blank=True, to='users.UserGroup', verbose_name='User group'), - ), - migrations.AlterField( - model_name='assetpermission', - name='users', - field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - migrations.AlterUniqueTogether( - name='remoteapppermission', - unique_together={('org_id', 'name')}, - ), - ] diff --git a/apps/perms/migrations/0006_auto_20190628_1921.py b/apps/perms/migrations/0006_auto_20190628_1921.py deleted file mode 100644 index f0faec017..000000000 --- a/apps/perms/migrations/0006_auto_20190628_1921.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-28 11:47 - -from django.db import migrations, models -from functools import reduce - - -def migrate_old_actions(apps, schema_editor): - from orgs.utils import set_to_root_org - set_to_root_org() - perm_model = apps.get_model('perms', 'AssetPermission') - db_alias = schema_editor.connection.alias - perms = perm_model.objects.using(db_alias).all() - actions_map = { - "all": 0b11111111, - "connect": 0b00000001, - "upload_file": 0b00000010, - "download_file": 0b00000100, - } - - for perm in perms: - actions = perm.actions.all() - if not actions: - continue - new_actions = [actions_map.get(action.name, 0b11111111) for action in actions] - new_action = reduce(lambda x, y: x | y, new_actions) - perm.action = new_action - perm.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0005_auto_20190521_1619'), - ] - - operations = [ - migrations.AddField( - model_name='assetpermission', - name='action', - field=models.IntegerField(choices=[(255, 'All'), (1, 'Connect'), (2, 'Upload file'), (4, 'Download file'), (6, 'Upload download')], default=255, verbose_name='Actions'), - ), - migrations.RunPython(migrate_old_actions), - ] diff --git a/apps/perms/migrations/0007_remove_assetpermission_actions.py b/apps/perms/migrations/0007_remove_assetpermission_actions.py deleted file mode 100644 index 31e083c88..000000000 --- a/apps/perms/migrations/0007_remove_assetpermission_actions.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-28 12:02 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0006_auto_20190628_1921'), - ] - - operations = [ - migrations.RemoveField( - model_name='assetpermission', - name='actions', - ), - migrations.RenameField( - model_name='assetpermission', - old_name='action', - new_name='actions', - ), - migrations.DeleteModel('action'), - ] diff --git a/apps/perms/migrations/0008_auto_20190911_1907.py b/apps/perms/migrations/0008_auto_20190911_1907.py deleted file mode 100644 index b7b5b5776..000000000 --- a/apps/perms/migrations/0008_auto_20190911_1907.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-11 11:07 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0007_remove_assetpermission_actions'), - ] - - operations = [ - migrations.AlterModelOptions( - name='assetpermission', - options={'ordering': ('name',), 'verbose_name': 'Asset permission'}, - ), - ] diff --git a/apps/perms/migrations/0009_remoteapppermission_system_users.py b/apps/perms/migrations/0009_remoteapppermission_system_users.py deleted file mode 100644 index 625a4c4e7..000000000 --- a/apps/perms/migrations/0009_remoteapppermission_system_users.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-16 02:57 - -from django.db import migrations, models - - -def migrate_system_user_from_remote_app_to_remote_app_perms(apps, schema_editor): - remote_app_perms_model = apps.get_model("perms", "RemoteAppPermission") - db_alias = schema_editor.connection.alias - perms = remote_app_perms_model.objects.using(db_alias).all() - for perm in perms: - system_users_ids = perm.remote_apps.values_list('system_user', flat=True) - perm.system_users.set(system_users_ids) - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0038_auto_20190911_1634'), - ('perms', '0008_auto_20190911_1907'), - ] - - operations = [ - migrations.AddField( - model_name='remoteapppermission', - name='system_users', - field=models.ManyToManyField(related_name='granted_by_remote_app_permissions', to='assets.SystemUser', verbose_name='System user'), - ), - migrations.RunPython( - code=migrate_system_user_from_remote_app_to_remote_app_perms, - ), - ] diff --git a/apps/perms/migrations/0010_auto_20191218_1705.py b/apps/perms/migrations/0010_auto_20191218_1705.py deleted file mode 100644 index c3144bc5d..000000000 --- a/apps/perms/migrations/0010_auto_20191218_1705.py +++ /dev/null @@ -1,47 +0,0 @@ -# Generated by Django 2.1.11 on 2019-12-18 09:05 - -import common.utils.django -from django.conf import settings -from django.db import migrations, models -import django.utils.timezone -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0024_auto_20191118_1612'), - ('assets', '0046_auto_20191218_1705'), - ('applications', '0004_auto_20191218_1705'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('perms', '0009_remoteapppermission_system_users'), - ] - - operations = [ - migrations.CreateModel( - name='DatabaseAppPermission', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), - ('date_start', models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date start')), - ('date_expired', models.DateTimeField(db_index=True, default=common.utils.django.date_expired_default, verbose_name='Date expired')), - ('created_by', models.CharField(blank=True, max_length=128, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('database_apps', models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='applications.DatabaseApp', verbose_name='DatabaseApp')), - ('system_users', models.ManyToManyField(related_name='granted_by_database_app_permissions', to='assets.SystemUser', verbose_name='System user')), - ('user_groups', models.ManyToManyField(blank=True, to='users.UserGroup', verbose_name='User group')), - ('users', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'verbose_name': 'DatabaseApp permission', - 'ordering': ('name',), - }, - ), - migrations.AlterUniqueTogether( - name='databaseapppermission', - unique_together={('org_id', 'name')}, - ), - ] diff --git a/apps/perms/migrations/0011_auto_20200721_1739.py b/apps/perms/migrations/0011_auto_20200721_1739.py deleted file mode 100644 index 1dcb33633..000000000 --- a/apps/perms/migrations/0011_auto_20200721_1739.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-21 09:39 - -from django.db import migrations, models - -from django.db.models import F - - -def migrate_asset_permission(apps, schema_editor): - # 已有的资产权限默认拥有剪切板复制粘贴动作 - asset_permission_model = apps.get_model('perms', 'AssetPermission') - asset_permission_model.objects.all().update(actions=F('actions').bitor(24)) - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0010_auto_20191218_1705'), - ] - - operations = [ - migrations.AlterField( - model_name='assetpermission', - name='actions', - field=models.IntegerField(choices=[(255, 'All'), (1, 'Connect'), (2, 'Upload file'), (4, 'Download file'), (6, 'Upload download'), (8, 'Clipboard copy'), (16, 'Clipboard paste'), (24, 'Clipboard copy paste')], default=255, verbose_name='Actions'), - ), - migrations.RunPython(migrate_asset_permission) - ] diff --git a/apps/perms/migrations/0012_k8sapppermission.py b/apps/perms/migrations/0012_k8sapppermission.py deleted file mode 100644 index c13b75ad1..000000000 --- a/apps/perms/migrations/0012_k8sapppermission.py +++ /dev/null @@ -1,44 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-07 07:13 - -import common.utils.django -from django.conf import settings -from django.db import migrations, models -import django.utils.timezone -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0054_auto_20200807_1032'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('applications', '0005_k8sapp'), - ('users', '0028_auto_20200728_1805'), - ('perms', '0011_auto_20200721_1739'), - ] - - operations = [ - migrations.CreateModel( - name='K8sAppPermission', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), - ('date_start', models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date start')), - ('date_expired', models.DateTimeField(db_index=True, default=common.utils.django.date_expired_default, verbose_name='Date expired')), - ('created_by', models.CharField(blank=True, max_length=128, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('k8s_apps', models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='applications.K8sApp', verbose_name='KubernetesApp')), - ('system_users', models.ManyToManyField(related_name='granted_by_k8s_app_permissions', to='assets.SystemUser', verbose_name='System user')), - ('user_groups', models.ManyToManyField(blank=True, to='users.UserGroup', verbose_name='User group')), - ('users', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'verbose_name': 'KubernetesApp permission', - 'ordering': ('name',), - 'unique_together': {('org_id', 'name')}, - }, - ), - ] diff --git a/apps/perms/migrations/0013_rebuildusertreetask_usergrantedmappingnode.py b/apps/perms/migrations/0013_rebuildusertreetask_usergrantedmappingnode.py deleted file mode 100644 index 09efa093c..000000000 --- a/apps/perms/migrations/0013_rebuildusertreetask_usergrantedmappingnode.py +++ /dev/null @@ -1,53 +0,0 @@ -# Generated by Django 2.2.13 on 2020-09-07 08:40 - -import assets.models.node -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0057_fill_node_value_assets_amount_and_parent_key'), - ('perms', '0012_k8sapppermission'), - ] - - operations = [ - migrations.CreateModel( - name='UserGrantedMappingNode', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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')), - ('key', models.CharField(db_index=True, max_length=64, verbose_name='Key')), - ('granted', models.BooleanField(db_index=True, default=False)), - ('asset_granted', models.BooleanField(db_index=True, default=False)), - ('parent_key', models.CharField(db_index=True, default='', max_length=64, verbose_name='Parent key')), - ('assets_amount', models.IntegerField(default=0)), - ('node', models.ForeignKey(db_constraint=False, default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='mapping_nodes', to='assets.Node')), - ('user', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'abstract': False, - }, - bases=(assets.models.node.FamilyMixin, models.Model), - ), - migrations.CreateModel( - name='RebuildUserTreeTask', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'abstract': False, - }, - ), - ] diff --git a/apps/perms/migrations/0014_build_users_perm_tree.py b/apps/perms/migrations/0014_build_users_perm_tree.py deleted file mode 100644 index a4fd97b96..000000000 --- a/apps/perms/migrations/0014_build_users_perm_tree.py +++ /dev/null @@ -1,13 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-21 08:20 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0013_rebuildusertreetask_usergrantedmappingnode'), - ] - - operations = [ - ] diff --git a/apps/perms/migrations/0015_auto_20200929_1728.py b/apps/perms/migrations/0015_auto_20200929_1728.py deleted file mode 100644 index 9b8388c3b..000000000 --- a/apps/perms/migrations/0015_auto_20200929_1728.py +++ /dev/null @@ -1,54 +0,0 @@ -# Generated by Django 2.2.13 on 2020-09-29 09:28 - -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0014_build_users_perm_tree'), - ] - - operations = [ - migrations.AlterField( - model_name='assetpermission', - name='user_groups', - field=models.ManyToManyField(blank=True, related_name='%(class)ss', to='users.usergroup', verbose_name='User group'), - ), - migrations.AlterField( - model_name='assetpermission', - name='users', - field=models.ManyToManyField(blank=True, related_name='%(class)ss', to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - migrations.AlterField( - model_name='databaseapppermission', - name='user_groups', - field=models.ManyToManyField(blank=True, related_name='databaseapppermissions', to='users.UserGroup', verbose_name='User group'), - ), - migrations.AlterField( - model_name='databaseapppermission', - name='users', - field=models.ManyToManyField(blank=True, related_name='databaseapppermissions', to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - migrations.AlterField( - model_name='k8sapppermission', - name='user_groups', - field=models.ManyToManyField(blank=True, related_name='k8sapppermissions', to='users.UserGroup', verbose_name='User group'), - ), - migrations.AlterField( - model_name='k8sapppermission', - name='users', - field=models.ManyToManyField(blank=True, related_name='k8sapppermissions', to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - migrations.AlterField( - model_name='remoteapppermission', - name='user_groups', - field=models.ManyToManyField(blank=True, related_name='remoteapppermissions', to='users.UserGroup', verbose_name='User group'), - ), - migrations.AlterField( - model_name='remoteapppermission', - name='users', - field=models.ManyToManyField(blank=True, related_name='remoteapppermissions', to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - ] diff --git a/apps/perms/migrations/0016_applicationpermission.py b/apps/perms/migrations/0016_applicationpermission.py deleted file mode 100644 index 04487e72d..000000000 --- a/apps/perms/migrations/0016_applicationpermission.py +++ /dev/null @@ -1,237 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-28 02:19 - -import common.utils.django -from django.conf import settings -from django.db import migrations, models -import django.utils.timezone -import uuid - - -def old_perm_to_application_permission_json(old_perm, category, _type): - return { - 'id': old_perm.id, - 'name': old_perm.name, - 'category': category, - 'type': _type, - 'is_active': old_perm.is_active, - 'date_start': old_perm.date_start, - 'date_expired': old_perm.date_expired, - 'created_by': old_perm.created_by, - 'comment': old_perm.comment, - 'org_id': old_perm.org_id - } - - -def common_old_perm_relation_to_application_permission_json(old_perm_relation, data_json): - return { - 'applicationpermission_id': getattr(old_perm_relation, data_json['relation_app_perm_id']), - } - - -def old_perm_relation_app_to_application_permission_json(old_perm_relation_app, data_json): - data = common_old_perm_relation_to_application_permission_json(old_perm_relation_app, data_json) - data.update({ - 'application_id': getattr(old_perm_relation_app, data_json['relation_app_id']) - }) - return data - - -def old_perm_relation_system_user_to_application_permission_json(old_perm_relation_system_user, data_json): - data = common_old_perm_relation_to_application_permission_json(old_perm_relation_system_user, data_json) - data.update({ - 'systemuser_id': old_perm_relation_system_user.systemuser_id, - }) - return data - - -def old_perm_relation_user_group_to_application_permission_json(old_perm_relation_user_group, data_json): - data = common_old_perm_relation_to_application_permission_json(old_perm_relation_user_group, data_json) - data.update({ - 'usergroup_id': old_perm_relation_user_group.usergroup_id, - }) - return data - - -def old_perm_relation_user_to_application_permission_json(old_perm_relation_user, data_json): - data = common_old_perm_relation_to_application_permission_json(old_perm_relation_user, data_json) - data.update({ - 'user_id': old_perm_relation_user.user_id, - }) - return data - - -CATEGORY_DB = 'db' -CATEGORY_REMOTE = 'remote_app' -CATEGORY_CLOUD = 'cloud' - -TYPE_DB_MYSQL = 'mysql' -TYPE_CLOUD_K8S = 'k8s' -TYPE_REMOTE_CHROME = 'chrome' -TYPE_REMOTE_MYSQL_WORKBENCH = 'mysql_workbench' -TYPE_REMOTE_VMWARE_CLIENT = 'vmware_client' -TYPE_REMOTE_CUSTOM = 'custom' - - -OLD_PERM_MODELS_NAME_MAP_DATA_JSON = { - 'DatabaseAppPermission': { - 'app_m2m_fields': 'database_apps', - 'relation_app_perm_id': 'databaseapppermission_id', - 'relation_app_id': 'databaseapp_id', - 'category': CATEGORY_DB, - 'type': TYPE_DB_MYSQL, - }, - 'RemoteAppPermission': { - 'app_m2m_fields': 'remote_apps', - 'relation_app_perm_id': 'remoteapppermission_id', - 'relation_app_id': 'remoteapp_id', - 'category': CATEGORY_REMOTE, - 'type': None, - }, - 'K8sAppPermission': { - 'app_m2m_fields': 'k8s_apps', - 'relation_app_perm_id': 'k8sapppermission_id', - 'relation_app_id': 'k8sapp_id', - 'category': CATEGORY_CLOUD, - 'type': TYPE_CLOUD_K8S, - } -} - - -def migrate_and_integrate_application_permissions(apps, schema_editor): - db_alias = schema_editor.connection.alias - - new_app_perms_json = [] - new_app_perms_relation_apps_json = [] - new_app_perms_relation_system_users_json = [] - new_app_perms_relation_user_groups_json = [] - new_app_perms_relation_users_json = [] - - for old_perm_model_name, data_json in OLD_PERM_MODELS_NAME_MAP_DATA_JSON.items(): - - # model - old_perm_model = apps.get_model("perms", old_perm_model_name) - - # instances - old_perms = old_perm_model.objects.using(db_alias).all() - old_perms_relation_apps = getattr(old_perm_model, data_json['app_m2m_fields']).through.objects.using(db_alias).all() - old_perms_relation_system_users = old_perm_model.system_users.through.objects.using(db_alias).all() - old_perms_relation_user_groups = old_perm_model.user_groups.through.objects.using(db_alias).all() - old_perms_relation_users = old_perm_model.users.through.objects.using(db_alias).all() - - # json - perms_json = [] - category = data_json['category'] - for old_perm in old_perms: - if category == CATEGORY_REMOTE: - type_list = list(old_perm.remote_apps.values_list('type', flat=True)) - if len(type_list) == 0: - _type = TYPE_REMOTE_CHROME - else: - _type = max(type_list, key=type_list.count) - else: - _type = data_json['type'] - perm_json = old_perm_to_application_permission_json(old_perm, category, _type) - perms_json.append(perm_json) - - perms_relation_apps_json = [ - old_perm_relation_app_to_application_permission_json(old_perm_relation_app, data_json) - for old_perm_relation_app in old_perms_relation_apps - ] - perms_relation_system_users_json = [ - old_perm_relation_system_user_to_application_permission_json(old_perm_relation_system_user, data_json) - for old_perm_relation_system_user in old_perms_relation_system_users - ] - perms_relation_user_groups_json = [ - old_perm_relation_user_group_to_application_permission_json(old_perm_relation_user_group, data_json) - for old_perm_relation_user_group in old_perms_relation_user_groups - ] - perms_relation_users_json = [ - old_perm_relation_user_to_application_permission_json(old_perm_relation_user, data_json) - for old_perm_relation_user in old_perms_relation_users - ] - - new_app_perms_json.extend(perms_json) - new_app_perms_relation_apps_json.extend(perms_relation_apps_json) - new_app_perms_relation_system_users_json.extend(perms_relation_system_users_json) - new_app_perms_relation_user_groups_json.extend(perms_relation_user_groups_json) - new_app_perms_relation_users_json.extend(perms_relation_users_json) - - # model - new_app_perm_model = apps.get_model("perms", "ApplicationPermission") - new_app_perm_relation_app_model = new_app_perm_model.applications.through - new_app_perm_relation_system_user_model = new_app_perm_model.system_users.through - new_app_perm_relation_user_group_model = new_app_perm_model.user_groups.through - new_app_perm_relation_user_model = new_app_perm_model.users.through - - # instances - new_app_perm_objects = [ - new_app_perm_model(**data) - for data in new_app_perms_json - ] - new_app_perm_relation_app_objects = [ - new_app_perm_relation_app_model(**data) - for data in new_app_perms_relation_apps_json - ] - new_app_perm_relation_system_user_objects = [ - new_app_perm_relation_system_user_model(**data) - for data in new_app_perms_relation_system_users_json - ] - new_app_perm_relation_user_group_objects = [ - new_app_perm_relation_user_group_model(**data) - for data in new_app_perms_relation_user_groups_json - ] - new_app_perm_relation_user_objects = [ - new_app_perm_relation_user_model(**data) - for data in new_app_perms_relation_users_json - ] - - # create - for new_app_perm_object in new_app_perm_objects: - if new_app_perm_model.objects.using(db_alias).filter(name=new_app_perm_object.name).exists(): - new_app_perm_object.name = '{}-{}'.format(new_app_perm_object.name, str(new_app_perm_object.id)[:4]) - new_app_perm_object.save() - new_app_perm_relation_app_model.objects.using(db_alias).bulk_create(new_app_perm_relation_app_objects) - new_app_perm_relation_system_user_model.objects.using(db_alias).bulk_create(new_app_perm_relation_system_user_objects) - new_app_perm_relation_user_group_model.objects.using(db_alias).bulk_create(new_app_perm_relation_user_group_objects) - new_app_perm_relation_user_model.objects.using(db_alias).bulk_create(new_app_perm_relation_user_objects) - - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0030_auto_20200819_2041'), - ('assets', '0059_auto_20201027_1905'), - ('applications', '0006_application'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('perms', '0015_auto_20200929_1728'), - ] - - operations = [ - migrations.CreateModel( - name='ApplicationPermission', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('is_active', models.BooleanField(default=True, verbose_name='Active')), - ('date_start', models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date start')), - ('date_expired', models.DateTimeField(db_index=True, default=common.utils.django.date_expired_default, verbose_name='Date expired')), - ('created_by', models.CharField(blank=True, max_length=128, verbose_name='Created by')), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('category', models.CharField(choices=[('db', 'Database'), ('remote_app', 'Remote app'), ('cloud', 'Cloud')], max_length=16, verbose_name='Category')), - ('type', models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type')), - ('applications', models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='applications.Application', verbose_name='Application')), - ('system_users', models.ManyToManyField(related_name='granted_by_application_permissions', to='assets.SystemUser', verbose_name='System user')), - ('user_groups', models.ManyToManyField(blank=True, related_name='applicationpermissions', to='users.UserGroup', verbose_name='User group')), - ('users', models.ManyToManyField(blank=True, related_name='applicationpermissions', to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'verbose_name': 'Application permission', - 'ordering': ('name',), - 'unique_together': {('org_id', 'name')}, - }, - ), - migrations.RunPython(migrate_and_integrate_application_permissions), - ] diff --git a/apps/perms/migrations/0017_auto_20210104_0435.py b/apps/perms/migrations/0017_auto_20210104_0435.py deleted file mode 100644 index d27efe6ee..000000000 --- a/apps/perms/migrations/0017_auto_20210104_0435.py +++ /dev/null @@ -1,62 +0,0 @@ -# Generated by Django 3.1 on 2021-01-03 20:35 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0016_applicationpermission'), - ] - - operations = [ - migrations.AlterUniqueTogether( - name='k8sapppermission', - unique_together=None, - ), - migrations.RemoveField( - model_name='k8sapppermission', - name='k8s_apps', - ), - migrations.RemoveField( - model_name='k8sapppermission', - name='system_users', - ), - migrations.RemoveField( - model_name='k8sapppermission', - name='user_groups', - ), - migrations.RemoveField( - model_name='k8sapppermission', - name='users', - ), - migrations.AlterUniqueTogether( - name='remoteapppermission', - unique_together=None, - ), - migrations.RemoveField( - model_name='remoteapppermission', - name='remote_apps', - ), - migrations.RemoveField( - model_name='remoteapppermission', - name='system_users', - ), - migrations.RemoveField( - model_name='remoteapppermission', - name='user_groups', - ), - migrations.RemoveField( - model_name='remoteapppermission', - name='users', - ), - migrations.DeleteModel( - name='DatabaseAppPermission', - ), - migrations.DeleteModel( - name='K8sAppPermission', - ), - migrations.DeleteModel( - name='RemoteAppPermission', - ), - ] diff --git a/apps/perms/migrations/0018_auto_20210208_1515.py b/apps/perms/migrations/0018_auto_20210208_1515.py deleted file mode 100644 index b5271f36f..000000000 --- a/apps/perms/migrations/0018_auto_20210208_1515.py +++ /dev/null @@ -1,65 +0,0 @@ -# Generated by Django 3.1 on 2021-02-08 07:15 - -import assets.models.node -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('assets', '0065_auto_20210121_1549'), - ('perms', '0017_auto_20210104_0435'), - ] - - operations = [ - migrations.CreateModel( - name='UserAssetGrantedTreeNodeRelation', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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')), - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('node_key', models.CharField(db_index=True, max_length=64, verbose_name='Key')), - ('node_parent_key', models.CharField(db_index=True, default='', max_length=64, verbose_name='Parent key')), - ('node_from', models.CharField(choices=[('granted', 'Direct node granted'), ('child', 'Have children node'), ('asset', 'Direct asset granted')], db_index=True, max_length=16)), - ('node_assets_amount', models.IntegerField(default=0)), - ('node', models.ForeignKey(db_constraint=False, default=None, on_delete=django.db.models.deletion.CASCADE, related_name='granted_node_rels', to='assets.node')), - ('user', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - options={ - 'abstract': False, - }, - bases=(assets.models.node.FamilyMixin, models.Model), - ), - migrations.RemoveField( - model_name='usergrantedmappingnode', - name='node', - ), - migrations.RemoveField( - model_name='usergrantedmappingnode', - name='user', - ), - migrations.CreateModel( - name='PermNode', - fields=[ - ], - options={ - 'ordering': [], - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.node',), - ), - migrations.DeleteModel( - name='RebuildUserTreeTask', - ), - migrations.DeleteModel( - name='UserGrantedMappingNode', - ), - ] diff --git a/apps/perms/migrations/0019_auto_20210906_1044.py b/apps/perms/migrations/0019_auto_20210906_1044.py deleted file mode 100644 index 42e480669..000000000 --- a/apps/perms/migrations/0019_auto_20210906_1044.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.12 on 2021-09-06 02:44 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0018_auto_20210208_1515'), - ] - - operations = [ - migrations.AddField( - model_name='applicationpermission', - name='from_ticket', - field=models.BooleanField(default=False, verbose_name='From ticket'), - ), - migrations.AddField( - model_name='assetpermission', - name='from_ticket', - field=models.BooleanField(default=False, verbose_name='From ticket'), - ), - ] diff --git a/apps/perms/migrations/0020_auto_20210910_1103.py b/apps/perms/migrations/0020_auto_20210910_1103.py deleted file mode 100644 index 0d01345f5..000000000 --- a/apps/perms/migrations/0020_auto_20210910_1103.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.1.12 on 2021-09-10 03:03 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0076_delete_assetuser'), - ('perms', '0019_auto_20210906_1044'), - ] - - operations = [ - migrations.AlterField( - model_name='assetpermission', - name='system_users', - field=models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.SystemUser', verbose_name='System user'), - ), - migrations.AlterField( - model_name='applicationpermission', - name='system_users', - field=models.ManyToManyField(blank=True, related_name='granted_by_application_permissions', to='assets.SystemUser', verbose_name='System user'), - ), - ] diff --git a/apps/perms/migrations/0021_auto_20211105_1605.py b/apps/perms/migrations/0021_auto_20211105_1605.py deleted file mode 100644 index f1d3c0043..000000000 --- a/apps/perms/migrations/0021_auto_20211105_1605.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.12 on 2021-11-05 08:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0020_auto_20210910_1103'), - ] - - operations = [ - migrations.AlterField( - model_name='applicationpermission', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/perms/migrations/0022_applicationpermission_actions.py b/apps/perms/migrations/0022_applicationpermission_actions.py deleted file mode 100644 index 3026b1326..000000000 --- a/apps/perms/migrations/0022_applicationpermission_actions.py +++ /dev/null @@ -1,26 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-20 06:55 - -from django.db import migrations, models - -ACTION_CONNECT = 1 - - -def migrate_app_perms_actions(apps, schema_editor): - perm_model = apps.get_model("perms", "ApplicationPermission") - perm_model.objects.all().update(actions=ACTION_CONNECT) - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0021_auto_20211105_1605'), - ] - - operations = [ - migrations.AddField( - model_name='applicationpermission', - name='actions', - field=models.IntegerField(choices=[(255, 'All'), (1, 'Connect'), (2, 'Upload file'), (4, 'Download file'), (6, 'Upload download'), (8, 'Clipboard copy'), (16, 'Clipboard paste'), (24, 'Clipboard copy paste')], default=255, verbose_name='Actions'), - ), - migrations.RunPython(migrate_app_perms_actions) - ] diff --git a/apps/perms/migrations/0023_auto_20220112_2035.py b/apps/perms/migrations/0023_auto_20220112_2035.py deleted file mode 100644 index 0cfa0e0cc..000000000 --- a/apps/perms/migrations/0023_auto_20220112_2035.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-01-12 12:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0022_applicationpermission_actions'), - ] - - operations = [ - migrations.AlterField( - model_name='applicationpermission', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('redis', 'Redis'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/perms/migrations/0024_auto_20220217_2135.py b/apps/perms/migrations/0024_auto_20220217_2135.py deleted file mode 100644 index 60e1a2ecf..000000000 --- a/apps/perms/migrations/0024_auto_20220217_2135.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-17 13:35 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0023_auto_20220112_2035'), - ] - - operations = [ - migrations.AlterModelOptions( - name='applicationpermission', - options={'ordering': ('name',), 'verbose_name': 'Application permission'}, - ), - migrations.AlterModelOptions( - name='assetpermission', - options={'ordering': ('name',), 'verbose_name': 'Asset permission'}, - ), - ] diff --git a/apps/perms/migrations/0025_auto_20220223_1539.py b/apps/perms/migrations/0025_auto_20220223_1539.py deleted file mode 100644 index 47d3487c7..000000000 --- a/apps/perms/migrations/0025_auto_20220223_1539.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-23 07:39 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0024_auto_20220217_2135'), - ] - - operations = [ - migrations.AlterField( - model_name='applicationpermission', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('mariadb', 'MariaDB'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/perms/migrations/0026_auto_20220307_1500.py b/apps/perms/migrations/0026_auto_20220307_1500.py deleted file mode 100644 index 7429c6408..000000000 --- a/apps/perms/migrations/0026_auto_20220307_1500.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-07 07:00 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0018_auto_20220223_1539'), - ('assets', '0088_auto_20220303_1612'), - ('perms', '0025_auto_20220223_1539'), - ] - - operations = [ - migrations.CreateModel( - name='PermedAsset', - fields=[ - ], - options={ - 'verbose_name': 'Permed asset', - 'permissions': [('view_myassets', 'Can view my assets'), ('view_userassets', 'Can view user assets'), ('view_usergroupassets', 'Can view usergroup assets')], - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('assets.asset',), - ), - ] diff --git a/apps/perms/migrations/0027_auto_20220310_1802.py b/apps/perms/migrations/0027_auto_20220310_1802.py deleted file mode 100644 index 48d9ffceb..000000000 --- a/apps/perms/migrations/0027_auto_20220310_1802.py +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-10 10:02 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('applications', '0018_auto_20220223_1539'), - ('perms', '0026_auto_20220307_1500'), - ] - - operations = [ - migrations.CreateModel( - name='PermedApplication', - fields=[ - ], - options={ - 'verbose_name': 'Permed application', - 'permissions': [('view_myapps', 'Can view my apps'), ('view_userapps', 'Can view user apps'), ('view_usergroupapps', 'Can view usergroup apps')], - 'proxy': True, - 'default_permissions': [], - 'indexes': [], - 'constraints': [], - }, - bases=('applications.application',), - ), - migrations.AlterModelOptions( - name='applicationpermission', - options={'ordering': ('name',), 'permissions': [], 'verbose_name': 'Application permission'}, - ), - migrations.AlterModelOptions( - name='assetpermission', - options={'ordering': ('name',), 'permissions': [], 'verbose_name': 'Asset permission'}, - ), - ] diff --git a/apps/perms/migrations/0028_auto_20220316_2028.py b/apps/perms/migrations/0028_auto_20220316_2028.py deleted file mode 100644 index a1a71e5f2..000000000 --- a/apps/perms/migrations/0028_auto_20220316_2028.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-16 12:28 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0027_auto_20220310_1802'), - ] - - operations = [ - migrations.AlterField( - model_name='applicationpermission', - name='type', - field=models.CharField(choices=[('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('oracle', 'Oracle'), ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/perms/migrations/0029_auto_20220728_1728.py b/apps/perms/migrations/0029_auto_20220728_1728.py deleted file mode 100644 index 0230e9aff..000000000 --- a/apps/perms/migrations/0029_auto_20220728_1728.py +++ /dev/null @@ -1,73 +0,0 @@ -from django.db import migrations - - -def migrate_app_perms_to_assets(apps, schema_editor): - asset_permission_model = apps.get_model("perms", "AssetPermission") - app_permission_model = apps.get_model("perms", "ApplicationPermission") - - count = 0 - bulk_size = 1000 - while True: - app_perms = app_permission_model.objects.all()[count:bulk_size] - if not app_perms: - break - count += len(app_perms) - attrs = [ - 'id', 'name', 'actions', 'is_active', 'date_start', - 'date_expired', 'created_by', 'from_ticket', 'comment', - 'org_id', - ] - asset_permissions = [] - - for app_perm in app_perms: - asset_permission = asset_permission_model() - for attr in attrs: - setattr(asset_permission, attr, getattr(app_perm, attr)) - asset_permission.name = f"App-{app_perm.name}" - asset_permissions.append(asset_permission) - asset_permission_model.objects.bulk_create(asset_permissions, ignore_conflicts=True) - - -def migrate_relations(apps, schema_editor): - asset_permission_model = apps.get_model("perms", "AssetPermission") - app_permission_model = apps.get_model("perms", "ApplicationPermission") - m2m_names = [ - ('applications', 'assets', 'application_id', 'asset_id'), - ('users', 'users', 'user_id', 'user_id'), - ('user_groups', 'user_groups', 'usergroup_id', 'usergroup_id'), - ('system_users', 'system_users', 'systemuser_id', 'systemuser_id'), - ] - - for app_name, asset_name, app_attr, asset_attr in m2m_names: - app_through = getattr(app_permission_model, app_name).through - asset_through = getattr(asset_permission_model, asset_name).through - - count = 0 - bulk_size = 1000 - - while True: - app_permission_relations = app_through.objects.all()[count:bulk_size] - if not app_permission_relations: - break - count += len(app_permission_relations) - asset_through_relations = [] - - for app_relation in app_permission_relations: - asset_relation = asset_through() - asset_relation.assetpermission_id = app_relation.applicationpermission_id - setattr(asset_relation, asset_attr, getattr(app_relation, app_attr)) - asset_through_relations.append(asset_relation) - - asset_through.objects.bulk_create(asset_through_relations, ignore_conflicts=True) - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0028_auto_20220316_2028'), - ] - - operations = [ - migrations.RunPython(migrate_app_perms_to_assets), - migrations.RunPython(migrate_relations), - ] diff --git a/apps/perms/migrations/0030_auto_20220816_1132.py b/apps/perms/migrations/0030_auto_20220816_1132.py deleted file mode 100644 index 3915b8b1a..000000000 --- a/apps/perms/migrations/0030_auto_20220816_1132.py +++ /dev/null @@ -1,41 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-16 03:32 -from django.db import migrations, models - - -def migrate_system_user_to_accounts(apps, schema_editor): - asset_permission_model = apps.get_model("perms", "AssetPermission") - - count = 0 - bulk_size = 10000 - while True: - asset_permissions = asset_permission_model.objects \ - .prefetch_related('system_users')[count:bulk_size] - if not asset_permissions: - break - - count += len(asset_permissions) - updated = [] - for asset_permission in asset_permissions: - asset_permission.accounts = [s.username for s in asset_permission.system_users.all()] - updated.append(asset_permission) - asset_permission_model.objects.bulk_update(updated, ['accounts']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0029_auto_20220728_1728'), - ] - - operations = [ - migrations.AddField( - model_name='assetpermission', - name='accounts', - field=models.JSONField(default=list, verbose_name='Account'), - ), - migrations.RunPython(migrate_system_user_to_accounts), - migrations.RemoveField( - model_name='assetpermission', - name='system_users', - ), - ] diff --git a/apps/perms/migrations/0031_auto_20220816_1600.py b/apps/perms/migrations/0031_auto_20220816_1600.py deleted file mode 100644 index b5ccbc24c..000000000 --- a/apps/perms/migrations/0031_auto_20220816_1600.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-16 08:00 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0030_auto_20220816_1132'), - ] - - operations = [ - migrations.AlterUniqueTogether( - name='applicationpermission', - unique_together=None, - ), - migrations.RemoveField( - model_name='applicationpermission', - name='applications', - ), - migrations.RemoveField( - model_name='applicationpermission', - name='system_users', - ), - migrations.RemoveField( - model_name='applicationpermission', - name='user_groups', - ), - migrations.RemoveField( - model_name='applicationpermission', - name='users', - ), - migrations.DeleteModel( - name='PermedApplication', - ), - migrations.DeleteModel( - name='ApplicationPermission', - ), - ] diff --git a/apps/perms/migrations/0032_auto_20221111_1919.py b/apps/perms/migrations/0032_auto_20221111_1919.py deleted file mode 100644 index 6ab787df0..000000000 --- a/apps/perms/migrations/0032_auto_20221111_1919.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 3.2.14 on 2022-11-11 11:19 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0101_auto_20220811_1511'), - ('accounts', '0001_initial'), - ('perms', '0031_auto_20220816_1600'), - ] - - operations = [ - migrations.CreateModel( - name='PermedAccount', - fields=[ - ], - options={ - 'verbose_name': 'Permed account', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('accounts.account',), - ), - migrations.AlterField( - model_name='assetpermission', - name='actions', - field=models.IntegerField(default=1, verbose_name='Actions'), - ), - ] diff --git a/apps/perms/migrations/0033_auto_20221220_1956.py b/apps/perms/migrations/0033_auto_20221220_1956.py deleted file mode 100644 index 1c10257d2..000000000 --- a/apps/perms/migrations/0033_auto_20221220_1956.py +++ /dev/null @@ -1,48 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - dependencies = [ - ('perms', '0032_auto_20221111_1919'), - ] - - operations = [ - migrations.AddField( - model_name='assetpermission', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='assetpermission', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='assetpermission', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='assetpermission', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='assetpermission', - name='date_created', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='userassetgrantedtreenoderelation', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='userassetgrantedtreenoderelation', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - ] diff --git a/apps/perms/migrations/0034_auto_20230525_1734.py b/apps/perms/migrations/0034_auto_20230525_1734.py deleted file mode 100644 index f1e842315..000000000 --- a/apps/perms/migrations/0034_auto_20230525_1734.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.17 on 2023-05-25 09:34 - -from django.db import migrations - - -def migrate_asset_permission_delete_perm(apps, *args): - asset_permission_cls = apps.get_model('perms', 'AssetPermission') - asset_permission_cls.objects.filter(actions__gte=31).update(actions=63) - - -class Migration(migrations.Migration): - dependencies = [ - ('perms', '0033_auto_20221220_1956'), - ] - - operations = [ - migrations.RunPython(migrate_asset_permission_delete_perm) - ] diff --git a/apps/perms/migrations/0035_auto_20231125_1025.py b/apps/perms/migrations/0035_auto_20231125_1025.py deleted file mode 100644 index cd3f433ba..000000000 --- a/apps/perms/migrations/0035_auto_20231125_1025.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-25 02:45 - -from django.db import migrations, models - -import perms.models.asset_permission - - -class Migration(migrations.Migration): - - dependencies = [ - ('perms', '0034_auto_20230525_1734'), - ] - - operations = [ - migrations.AddField( - model_name='assetpermission', - name='protocols', - field=models.JSONField(default=perms.models.asset_permission.default_protocols, verbose_name='Protocols'), - ), - ] diff --git a/apps/perms/migrations/0036_auto_20231108_1626.py b/apps/perms/migrations/0036_auto_20231108_1626.py deleted file mode 100644 index a0777abc5..000000000 --- a/apps/perms/migrations/0036_auto_20231108_1626.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-08 08:26 - -from django.db import migrations - - -def migrate_action_all_value(apps, schema_editor): - old_max_bit = 63 - new_max_bit = 4095 - asset_permission_model = apps.get_model("perms", "AssetPermission") - db_alias = schema_editor.connection.alias - perms = list(asset_permission_model.objects.using(db_alias).filter(actions=old_max_bit)) - for perm in perms: - perm.actions = new_max_bit - asset_permission_model.objects.bulk_update(perms, ['actions']) - - -class Migration(migrations.Migration): - dependencies = [ - ('perms', '0035_auto_20231125_1025'), - ] - operations = [ - migrations.RunPython( - code=migrate_action_all_value, - ), - ] diff --git a/apps/rbac/migrations/0001_initial.py b/apps/rbac/migrations/0001_initial.py index 624b88dd3..9e56fda5f 100644 --- a/apps/rbac/migrations/0001_initial.py +++ b/apps/rbac/migrations/0001_initial.py @@ -1,24 +1,20 @@ -# Generated by Django 3.1.13 on 2021-11-19 08:29 - -import uuid +# Generated by Django 4.1.13 on 2024-05-09 03:16 import django.contrib.auth.models import django.contrib.contenttypes.models -import django.db.models.deletion -from django.conf import settings from django.db import migrations, models - -import common.db.models +import django.db.models.deletion +import uuid class Migration(migrations.Migration): + initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('auth', '0012_alter_user_first_name_max_length'), ('contenttypes', '0002_remove_content_type_name'), - ('orgs', '0010_auto_20210219_1241'), + ('auth', '0012_alter_user_first_name_max_length'), + ('orgs', '0001_initial'), ] operations = [ @@ -29,25 +25,26 @@ class Migration(migrations.Migration): ], options={ 'verbose_name': 'Menu permission', - 'permissions': [('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'), - ('view_workspace', 'Can view workbench view')], + 'permissions': [('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'), ('view_workbench', 'Can view workbench view'), ('view_webterminal', 'Can view web terminal'), ('view_filemanager', 'Can view file manager'), ('view_systemtools', 'Can view System Tools')], 'default_permissions': [], }, ), migrations.CreateModel( name='Role', fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), + ('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)), ('name', models.CharField(max_length=128, verbose_name='Name')), - ('scope', models.CharField(choices=[('system', 'System'), ('org', 'Organization')], default='system', - max_length=128, verbose_name='Scope')), + ('scope', models.CharField(choices=[('system', 'System'), ('org', 'Organization')], default='system', max_length=128, verbose_name='Scope')), ('builtin', models.BooleanField(default=False, verbose_name='Builtin')), ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), ], + options={ + 'verbose_name': 'Role', + }, ), migrations.CreateModel( name='ContentType', @@ -68,6 +65,7 @@ class Migration(migrations.Migration): fields=[ ], options={ + 'verbose_name': 'Permissions', 'proxy': True, 'indexes': [], 'constraints': [], @@ -80,82 +78,18 @@ class Migration(migrations.Migration): migrations.CreateModel( name='RoleBinding', fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), + ('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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('scope', models.CharField(choices=[('system', 'System'), ('org', 'Organization')], default='system', - max_length=128, verbose_name='Scope')), - ('org', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, - related_name='role_bindings', to='orgs.organization', - verbose_name='Organization')), - ('role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='role_bindings', - to='rbac.role', verbose_name='Role')), - ('user', models.ForeignKey(on_delete=common.db.models.CASCADE_SIGNAL_SKIP, related_name='role_bindings', - to=settings.AUTH_USER_MODEL, verbose_name='User')), + ('scope', models.CharField(choices=[('system', 'System'), ('org', 'Organization')], default='system', max_length=128, verbose_name='Scope')), + ('org', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='role_bindings', to='orgs.organization', verbose_name='Organization')), + ('role', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='role_bindings', to='rbac.role', verbose_name='Role')), ], options={ 'verbose_name': 'Role binding', - 'unique_together': {('user', 'role', 'org')}, }, ), - migrations.AddField( - model_name='role', - name='permissions', - field=models.ManyToManyField(blank=True, related_name='roles', to='rbac.Permission', - verbose_name='Permissions'), - ), - migrations.AlterUniqueTogether( - name='role', - unique_together={('name', 'scope')}, - ), - migrations.CreateModel( - name='OrgRoleBinding', - fields=[ - ], - options={ - 'verbose_name': 'Organization role binding', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('rbac.rolebinding',), - ), - migrations.CreateModel( - name='SystemRoleBinding', - fields=[ - ], - options={ - 'verbose_name': 'System role binding', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('rbac.rolebinding',), - ), - migrations.CreateModel( - name='OrgRole', - fields=[ - ], - options={ - 'verbose_name': 'Organization role', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('rbac.role',), - ), - migrations.CreateModel( - name='SystemRole', - fields=[ - ], - options={ - 'verbose_name': 'System role', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('rbac.role',), - ), ] diff --git a/apps/rbac/migrations/0002_auto_20210929_1409.py b/apps/rbac/migrations/0002_auto_20210929_1409.py index 514a2d78f..31906a6e6 100644 --- a/apps/rbac/migrations/0002_auto_20210929_1409.py +++ b/apps/rbac/migrations/0002_auto_20210929_1409.py @@ -1,21 +1,85 @@ -# Generated by Django 3.1.13 on 2021-11-30 02:37 +# Generated by Django 4.1.13 on 2024-05-09 03:16 + +import common.db.models +from django.conf import settings +from django.db import migrations, models -from django.db import migrations class Migration(migrations.Migration): + initial = True + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('rbac', '0001_initial'), ] operations = [ - migrations.AlterModelOptions( - name='permission', - options={'verbose_name': 'Permissions'}, + migrations.AddField( + model_name='rolebinding', + name='user', + field=models.ForeignKey(on_delete=common.db.models.CASCADE_SIGNAL_SKIP, related_name='role_bindings', to=settings.AUTH_USER_MODEL, verbose_name='User'), ), - migrations.AlterModelOptions( + migrations.AddField( + model_name='role', + name='permissions', + field=models.ManyToManyField(blank=True, related_name='roles', to='rbac.permission', verbose_name='Permissions'), + ), + migrations.CreateModel( + name='OrgRole', + fields=[ + ], + options={ + 'verbose_name': 'Organization role', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('rbac.role',), + ), + migrations.CreateModel( + name='OrgRoleBinding', + fields=[ + ], + options={ + 'verbose_name': 'Organization role binding', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('rbac.rolebinding',), + ), + migrations.CreateModel( + name='SystemRole', + fields=[ + ], + options={ + 'verbose_name': 'System role', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('rbac.role',), + ), + migrations.CreateModel( + name='SystemRoleBinding', + fields=[ + ], + options={ + 'verbose_name': 'System role binding', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('rbac.rolebinding',), + ), + migrations.AlterUniqueTogether( + name='rolebinding', + unique_together={('user', 'role', 'org')}, + ), + migrations.AlterUniqueTogether( name='role', - options={'verbose_name': 'Role'}, - ) + unique_together={('name', 'scope')}, + ), ] diff --git a/apps/rbac/migrations/0003_auto_20211130_1037.py b/apps/rbac/migrations/0003_auto_20211130_1037.py index b72b56876..2e9db1923 100644 --- a/apps/rbac/migrations/0003_auto_20211130_1037.py +++ b/apps/rbac/migrations/0003_auto_20211130_1037.py @@ -1,6 +1,9 @@ -# Generated by Django 3.1.13 on 2021-12-01 11:01 +# Generated by Django 4.1.13 on 2024-05-09 03:16 + +import common.db.models +from django.conf import settings +from django.db import migrations, models -from django.db import migrations from rbac.builtin import BuiltinRole @@ -8,6 +11,19 @@ def create_builtin_roles(apps, schema_editor): BuiltinRole.sync_to_db(show_msg=True) +def set_admin_roles(apps, schema_editor): + User = apps.get_model('users', 'User') + Role = apps.get_model('rbac', 'Role') + Org = apps.get_model('orgs', 'Organization') + RoleBinding = apps.get_model('rbac', 'RoleBinding') + user = User.objects.get(username='admin') + system_role = Role.objects.get(name='SystemAdmin') + org_role = Role.objects.get(name='OrgAdmin') + org = Org.objects.get(id='00000000-0000-0000-0000-000000000002') + RoleBinding.objects.create(user=user, role=system_role, scope='system') + RoleBinding.objects.create(user=user, role=org_role, scope='org', org=org) + + class Migration(migrations.Migration): dependencies = [ @@ -15,5 +31,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RunPython(create_builtin_roles) + migrations.RunPython(create_builtin_roles), + migrations.RunPython(set_admin_roles), ] diff --git a/apps/rbac/migrations/0004_auto_20211201_1901.py b/apps/rbac/migrations/0004_auto_20211201_1901.py deleted file mode 100644 index 669af02cf..000000000 --- a/apps/rbac/migrations/0004_auto_20211201_1901.py +++ /dev/null @@ -1,80 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-01 11:01 - -import time -from django.db import migrations - -from rbac.builtin import BuiltinRole - - -def migrate_system_role_binding(apps, schema_editor): - db_alias = schema_editor.connection.alias - user_model = apps.get_model('users', 'User') - role_binding_model = apps.get_model('rbac', 'SystemRoleBinding') - - count = 0 - bulk_size = 1000 - print('') - while True: - users = user_model.objects.using(db_alias) \ - .only('role', 'id') \ - .all()[count:count+bulk_size] - if not users: - break - - role_bindings = [] - start = time.time() - for user in users: - role = BuiltinRole.get_system_role_by_old_name(user.role) - role_binding = role_binding_model(scope='system', user_id=user.id, role_id=role.id) - role_bindings.append(role_binding) - - role_binding_model.objects.bulk_create(role_bindings, ignore_conflicts=True) - print("\tCreate role binding: {}-{} using: {:.2f}s".format( - count, count + len(users), time.time()-start - )) - count += len(users) - - -def migrate_org_role_binding(apps, schema_editor): - db_alias = schema_editor.connection.alias - org_member_model = apps.get_model('orgs', 'OrganizationMember') - role_binding_model = apps.get_model('rbac', 'RoleBinding') - - count = 0 - bulk_size = 1000 - - while True: - members = org_member_model.objects.using(db_alias)\ - .only('role', 'user_id', 'org_id')\ - .all()[count:count+bulk_size] - if not members: - break - role_bindings = [] - start = time.time() - - for member in members: - role = BuiltinRole.get_org_role_by_old_name(member.role) - role_binding = role_binding_model( - scope='org', - user_id=member.user_id, - role_id=role.id, - org_id=member.org_id - ) - role_bindings.append(role_binding) - role_binding_model.objects.bulk_create(role_bindings, ignore_conflicts=True) - print("\tCreate role binding: {}-{} using: {:.2f}s".format( - count, count + len(members), time.time()-start - )) - count += len(members) - - -class Migration(migrations.Migration): - - dependencies = [ - ('rbac', '0003_auto_20211130_1037'), - ] - - operations = [ - migrations.RunPython(migrate_system_role_binding), - migrations.RunPython(migrate_org_role_binding) - ] diff --git a/apps/rbac/migrations/0005_auto_20220307_1524.py b/apps/rbac/migrations/0005_auto_20220307_1524.py deleted file mode 100644 index ba4427709..000000000 --- a/apps/rbac/migrations/0005_auto_20220307_1524.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-07 07:46 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('rbac', '0004_auto_20211201_1901'), - ] - - operations = [ - migrations.AlterModelOptions( - name='menupermission', - options={'default_permissions': [], 'permissions': [('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'), ('view_workspace', 'Can view workbench view'), ('view_webterminal', 'Can view web terminal'), ('view_filemanager', 'Can view file manager')], 'verbose_name': 'Menu permission'}, - ), - ] diff --git a/apps/rbac/migrations/0006_auto_20220310_0616.py b/apps/rbac/migrations/0006_auto_20220310_0616.py deleted file mode 100644 index 7e3ba72de..000000000 --- a/apps/rbac/migrations/0006_auto_20220310_0616.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-09 22:16 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('rbac', '0005_auto_20220307_1524'), - ] - - operations = [ - migrations.AlterModelOptions( - name='menupermission', - options={'default_permissions': [], 'permissions': [('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'), ('view_workspace', 'Can view workbench view'), ('view_webterminal', 'Can view web terminal'), ('view_filemanager', 'Can view file manager') ], 'verbose_name': 'Menu permission'}, - ), - ] diff --git a/apps/rbac/migrations/0007_auto_20220314_1525.py b/apps/rbac/migrations/0007_auto_20220314_1525.py deleted file mode 100644 index f861dc964..000000000 --- a/apps/rbac/migrations/0007_auto_20220314_1525.py +++ /dev/null @@ -1,30 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-14 07:25 - -from django.db import migrations - - -def migrate_old_permissions(apps, *args): - ContentType = apps.get_model('rbac', 'ContentType') - content_type_delete_required = [ - ('common', 'permission'), - ('applications', 'databaseapp'), - ('applications', 'k8sapp'), - ('applications', 'remoteapp'), - ('perms', 'databaseapppermission'), - ('perms', 'k8sapppermission'), - ('perms', 'remoteapppermission'), - ('authentication', 'loginconfirmsetting'), - ] - for app, model in content_type_delete_required: - ContentType.objects.filter(app_label=app, model=model).delete() - - -class Migration(migrations.Migration): - - dependencies = [ - ('rbac', '0006_auto_20220310_0616'), - ] - - operations = [ - migrations.RunPython(migrate_old_permissions) - ] diff --git a/apps/rbac/migrations/0008_auto_20220411_1709.py b/apps/rbac/migrations/0008_auto_20220411_1709.py deleted file mode 100644 index 319fa5a37..000000000 --- a/apps/rbac/migrations/0008_auto_20220411_1709.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-11 09:09 - -from django.db import migrations - - -def migrate_workspace_to_workbench(apps, *args): - model = apps.get_model('auth', 'Permission') - model.objects.filter(codename='view_workspace').delete() - - -class Migration(migrations.Migration): - - dependencies = [ - ('rbac', '0007_auto_20220314_1525'), - ] - - operations = [ - migrations.AlterModelOptions( - name='menupermission', - options={'default_permissions': [], 'permissions': [('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'), ('view_workbench', 'Can view workbench view'), ('view_webterminal', 'Can view web terminal'), ('view_filemanager', 'Can view file manager')], 'verbose_name': 'Menu permission'}, - ), - ] diff --git a/apps/rbac/migrations/0009_auto_20220411_1724.py b/apps/rbac/migrations/0009_auto_20220411_1724.py deleted file mode 100644 index 4ffb51068..000000000 --- a/apps/rbac/migrations/0009_auto_20220411_1724.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-11 09:24 - -from django.db import migrations - - -def migrate_workspace_to_workbench(apps, *args): - model = apps.get_model('auth', 'Permission') - model.objects.filter(codename='view_workspace').delete() - - -class Migration(migrations.Migration): - - dependencies = [ - ('rbac', '0008_auto_20220411_1709'), - ] - - operations = [ - migrations.RunPython(migrate_workspace_to_workbench) - ] diff --git a/apps/rbac/migrations/0010_auto_20221220_1956.py b/apps/rbac/migrations/0010_auto_20221220_1956.py deleted file mode 100644 index 0dee17c55..000000000 --- a/apps/rbac/migrations/0010_auto_20221220_1956.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('rbac', '0009_auto_20220411_1724'), - ] - - operations = [ - migrations.AddField( - model_name='rolebinding', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='role', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='role', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='rolebinding', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='rolebinding', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - ] diff --git a/apps/rbac/migrations/0011_remove_redundant_permission.py b/apps/rbac/migrations/0011_remove_redundant_permission.py deleted file mode 100644 index 6febd432c..000000000 --- a/apps/rbac/migrations/0011_remove_redundant_permission.py +++ /dev/null @@ -1,43 +0,0 @@ -# Generated by Django 3.2.16 on 2022-12-27 02:41 - -from django.db import migrations - - -def migrate_remove_redundant_permission(apps, *args): - model = apps.get_model('rbac', 'ContentType') - model.objects.filter(app_label='applications').delete() - model.objects.filter(app_label='ops', model__in=[ - 'task', 'commandexecution' - ]).delete() - - model.objects.filter(app_label='xpack', model__in=[ - 'applicationchangeauthplan', 'applicationchangeauthplanexecution', - 'applicationchangeauthplantask', 'changeauthplan', 'changeauthplanexecution', - 'changeauthplantask', 'gatherusertask', 'gatherusertaskexecution' - ]).delete() - - model.objects.filter(app_label='assets', model__in=[ - 'authbook', 'historicalauthbook', 'test_gateway', - 'accountbackupplan', 'accountbackupplanexecution', - 'gathereduser', 'systemuser' - ]).delete() - - model.objects.filter(app_label='perms', model__in=[ - 'applicationpermission', 'permedapplication', 'commandfilterrule', 'historicalauthbook' - ]).delete() - - perm_model = apps.get_model('auth', 'Permission') - perm_model.objects.filter(codename__in=[ - 'view_permusergroupasset', 'view_permuserasset', 'push_assetsystemuser', - 'add_assettonode', 'move_assettonode', 'remove_assetfromnode', - ]).delete() - - -class Migration(migrations.Migration): - dependencies = [ - ('rbac', '0010_auto_20221220_1956'), - ] - - operations = [ - migrations.RunPython(migrate_remove_redundant_permission) - ] diff --git a/apps/rbac/migrations/0012_remove_add_changesecretexection_permission.py b/apps/rbac/migrations/0012_remove_add_changesecretexection_permission.py deleted file mode 100644 index a402360dc..000000000 --- a/apps/rbac/migrations/0012_remove_add_changesecretexection_permission.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-20 07:01 - -from django.db import migrations - - -def migrate_remove_add_changesecretexection_permission(apps, *args): - perm_model = apps.get_model('auth', 'Permission') - perm_model.objects.filter(codename='add_changesecretexection').delete() - - -class Migration(migrations.Migration): - dependencies = [ - ('rbac', '0011_remove_redundant_permission'), - ] - - operations = [ - migrations.RunPython(migrate_remove_add_changesecretexection_permission) - ] diff --git a/apps/rbac/migrations/0013_alter_menupermission_options.py b/apps/rbac/migrations/0013_alter_menupermission_options.py deleted file mode 100644 index 8a1ace899..000000000 --- a/apps/rbac/migrations/0013_alter_menupermission_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-01 14:11 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('rbac', '0012_remove_add_changesecretexection_permission'), - ] - - operations = [ - migrations.AlterModelOptions( - name='menupermission', - options={'default_permissions': [], 'permissions': [('view_console', 'Can view console view'), ('view_audit', 'Can view audit view'), ('view_workbench', 'Can view workbench view'), ('view_webterminal', 'Can view web terminal'), ('view_filemanager', 'Can view file manager'), ('view_systemtools', 'Can view System Tools')], 'verbose_name': 'Menu permission'}, - ), - ] diff --git a/apps/rbac/migrations/0014_auto_20231208_1548.py b/apps/rbac/migrations/0014_auto_20231208_1548.py deleted file mode 100644 index 5fb8cefb7..000000000 --- a/apps/rbac/migrations/0014_auto_20231208_1548.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-12-08 07:48 - -from django.db import migrations - - -def migrate_update_offline_usersession_permission_name(apps, *args): - perm_model = apps.get_model('auth', 'Permission') - perm_model.objects.filter(codename='offline_usersession').update(name='Offline user session') - - -class Migration(migrations.Migration): - dependencies = [ - ('rbac', '0013_alter_menupermission_options'), - ] - - operations = [ - migrations.RunPython(migrate_update_offline_usersession_permission_name) - ] diff --git a/apps/settings/migrations/0001_initial.py b/apps/settings/migrations/0001_initial.py index 26ba90b00..47fbb5d4c 100644 --- a/apps/settings/migrations/0001_initial.py +++ b/apps/settings/migrations/0001_initial.py @@ -1,6 +1,7 @@ -# Generated by Django 2.1.7 on 2019-02-26 03:11 +# Generated by Django 4.1.13 on 2024-05-09 03:16 from django.db import migrations, models +import uuid class Migration(migrations.Migration): @@ -8,32 +9,41 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('common', '0006_auto_20190304_1515'), - ] - - state_operations = [ - migrations.CreateModel( - name='Setting', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, - serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=128, unique=True, - verbose_name='Name')), - ('value', models.TextField(verbose_name='Value')), - ('category', - models.CharField(default='default', max_length=128, verbose_name='Category')), - ('encrypted', models.BooleanField(default=False, verbose_name='Encrypted')), - ('enabled', - models.BooleanField(default=True, verbose_name='Enabled')), - ('comment', models.TextField(verbose_name='Comment')), - ], - options={ - 'verbose_name': 'Setting', - 'db_table': 'settings_setting', - }, - ), ] operations = [ - migrations.SeparateDatabaseAndState(state_operations=state_operations) + migrations.CreateModel( + name='ChatPrompt', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('content', models.TextField(verbose_name='Content')), + ('builtin', models.BooleanField(default=False, verbose_name='Builtin')), + ], + options={ + 'verbose_name': 'Chat prompt', + }, + ), + migrations.CreateModel( + name='Setting', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('value', models.TextField(blank=True, null=True, verbose_name='Value')), + ('category', models.CharField(default='default', max_length=128, verbose_name='Category')), + ('encrypted', models.BooleanField(default=False, verbose_name='Encrypted')), + ('enabled', models.BooleanField(default=True, verbose_name='Enabled')), + ('comment', models.TextField(verbose_name='Comment')), + ], + options={ + 'verbose_name': 'System setting', + 'db_table': 'settings_setting', + 'permissions': [('change_email', 'Can change email setting'), ('change_auth', 'Can change auth setting'), ('change_ops', 'Can change auth ops'), ('change_ticket', 'Can change auth ticket'), ('change_virtualapp', 'Can change virtual app setting'), ('change_announcement', 'Can change auth announcement'), ('change_vault', 'Can change vault setting'), ('change_chatai', 'Can change chat ai setting'), ('change_systemmsgsubscription', 'Can change system msg sub setting'), ('change_sms', 'Can change sms setting'), ('change_security', 'Can change security setting'), ('change_clean', 'Can change clean setting'), ('change_interface', 'Can change interface setting'), ('change_license', 'Can change license setting'), ('change_terminal', 'Can change terminal setting'), ('change_other', 'Can change other setting')], + }, + ), ] diff --git a/apps/settings/migrations/0002_auto_20210729_1546.py b/apps/settings/migrations/0002_auto_20210729_1546.py deleted file mode 100644 index 0b460f9a3..000000000 --- a/apps/settings/migrations/0002_auto_20210729_1546.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.1 on 2021-07-29 07:46 - -from django.db import migrations - - -def migrate_security_mfa_auth(apps, schema_editor): - setting_model = apps.get_model("settings", "Setting") - db_alias = schema_editor.connection.alias - - mfa_setting = setting_model.objects.using(db_alias).filter(name='SECURITY_MFA_AUTH').first() - if not mfa_setting: - return - - if mfa_setting.value == 'true': - mfa_setting.value = 1 - else: - mfa_setting.value = 0 - mfa_setting.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('settings', '0001_initial'), - ] - - operations = [ - migrations.RunPython(migrate_security_mfa_auth) - ] diff --git a/apps/settings/migrations/0003_auto_20210901_1035.py b/apps/settings/migrations/0003_auto_20210901_1035.py deleted file mode 100644 index c6f37625a..000000000 --- a/apps/settings/migrations/0003_auto_20210901_1035.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.12 on 2021-09-01 02:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('settings', '0002_auto_20210729_1546'), - ] - - operations = [ - migrations.AlterField( - model_name='setting', - name='value', - field=models.TextField(blank=True, null=True, verbose_name='Value'), - ), - ] diff --git a/apps/settings/migrations/0004_auto_20220211_1401.py b/apps/settings/migrations/0004_auto_20220211_1401.py deleted file mode 100644 index 72c9c62f8..000000000 --- a/apps/settings/migrations/0004_auto_20220211_1401.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.12 on 2022-02-11 06:01 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('settings', '0003_auto_20210901_1035'), - ] - - operations = [ - migrations.AlterModelOptions( - name='setting', - options={'verbose_name': 'System setting'}, - ), - ] diff --git a/apps/settings/migrations/0005_auto_20220310_0616.py b/apps/settings/migrations/0005_auto_20220310_0616.py deleted file mode 100644 index 6bfd753b3..000000000 --- a/apps/settings/migrations/0005_auto_20220310_0616.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-09 22:16 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('settings', '0004_auto_20220211_1401'), - ] - - operations = [ - migrations.AlterModelOptions( - name='setting', - options={'permissions': [('change_email', 'Can change email setting'), ('change_auth', 'Can change auth setting'), ('change_systemmsgsubscription', 'Can change system msg sub setting'), ('change_sms', 'Can change sms setting'), ('change_security', 'Can change security setting'), ('change_clean', 'Can change clean setting'), ('change_interface', 'Can change interface setting'), ('change_license', 'Can change license setting'), ('change_terminal', 'Can change terminal setting'), ('change_other', 'Can change other setting')], 'verbose_name': 'System setting'}, - ), - ] diff --git a/apps/settings/migrations/0006_remove_setting_enabled.py b/apps/settings/migrations/0006_remove_setting_enabled.py deleted file mode 100644 index 0982bc0f2..000000000 --- a/apps/settings/migrations/0006_remove_setting_enabled.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1.14 on 2022-06-06 09:45 - -from django.db import migrations - - -def migrate_terminal_razor_enabled(apps, schema_editor): - setting_model = apps.get_model("settings", "Setting") - s = setting_model.objects.filter(name='XRDP_ENABLED').first() - if not s: - return - s.name = 'TERMINAL_RAZOR_ENABLED' - s.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('settings', '0005_auto_20220310_0616'), - ] - - operations = [ - migrations.RunPython(migrate_terminal_razor_enabled), - ] diff --git a/apps/settings/migrations/0007_migrate_ldap_sync_org_ids.py b/apps/settings/migrations/0007_migrate_ldap_sync_org_ids.py deleted file mode 100644 index 44b696b25..000000000 --- a/apps/settings/migrations/0007_migrate_ldap_sync_org_ids.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 3.2.19 on 2023-05-25 09:00 -import json - -from django.db import migrations - - -def migrate_ldap_sync_org_ids(apps, schema_editor): - setting_model = apps.get_model("settings", "Setting") - db_alias = schema_editor.connection.alias - - instance = setting_model.objects.using(db_alias).filter(name='AUTH_LDAP_SYNC_ORG_ID').first() - if not instance: - return - ldap_sync_org_id = json.loads(instance.value) - setting_model.objects.using(db_alias).update_or_create( - name='AUTH_LDAP_SYNC_ORG_IDS', category='ldap', - value=json.dumps([ldap_sync_org_id]) - ) - instance.delete() - - -class Migration(migrations.Migration): - dependencies = [ - ('settings', '0006_remove_setting_enabled'), - ] - - operations = [ - migrations.RunPython(migrate_ldap_sync_org_ids) - ] diff --git a/apps/settings/migrations/0008_alter_setting_options.py b/apps/settings/migrations/0008_alter_setting_options.py deleted file mode 100644 index 9a8691d69..000000000 --- a/apps/settings/migrations/0008_alter_setting_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-30 10:37 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('settings', '0007_migrate_ldap_sync_org_ids'), - ] - - operations = [ - migrations.AlterModelOptions( - name='setting', - options={'permissions': [('change_email', 'Can change email setting'), ('change_auth', 'Can change auth setting'), ('change_vault', 'Can change vault setting'), ('change_systemmsgsubscription', 'Can change system msg sub setting'), ('change_sms', 'Can change sms setting'), ('change_security', 'Can change security setting'), ('change_clean', 'Can change clean setting'), ('change_interface', 'Can change interface setting'), ('change_license', 'Can change license setting'), ('change_terminal', 'Can change terminal setting'), ('change_other', 'Can change other setting')], 'verbose_name': 'System setting'}, - ), - ] diff --git a/apps/settings/migrations/0009_alter_cas_username_attribute.py b/apps/settings/migrations/0009_alter_cas_username_attribute.py deleted file mode 100644 index 7e5ba7428..000000000 --- a/apps/settings/migrations/0009_alter_cas_username_attribute.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-30 10:37 -import json - -from django.db import migrations - - -def migrate_cas_setting(apps, schema_editor): - setting_model = apps.get_model('settings', 'Setting') - obj = setting_model.objects.filter(name='CAS_RENAME_ATTRIBUTES').first() - if obj: - try: - value = json.loads(obj.value) - except Exception: - print("Invalid CAS_RENAME_ATTRIBUTES setting, skip") - return - - if value.pop('uid', None): - setting_model.objects.filter(name='CAS_USERNAME_ATTRIBUTE').update(value='"cas:user"') - value['cas:user'] = 'username' - obj.value = json.dumps(value) - obj.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('settings', '0008_alter_setting_options'), - ] - - operations = [ - migrations.RunPython(migrate_cas_setting), - ] diff --git a/apps/settings/migrations/0010_alter_setting_options.py b/apps/settings/migrations/0010_alter_setting_options.py deleted file mode 100644 index 0ce372e76..000000000 --- a/apps/settings/migrations/0010_alter_setting_options.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-19 07:08 - -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('settings', '0009_alter_cas_username_attribute'), - ] - - operations = [ - migrations.AlterModelOptions( - name='setting', - options={'permissions': [ - ('change_email', 'Can change email setting'), - ('change_auth', 'Can change auth setting'), - ('change_ops', 'Can change auth ops'), - ('change_ticket', 'Can change auth ticket'), - ('change_announcement', 'Can change auth announcement'), - ('change_vault', 'Can change vault setting'), - ('change_chatai', 'Can change chat ai setting'), - ('change_systemmsgsubscription', 'Can change system msg sub setting'), - ('change_sms', 'Can change sms setting'), - ('change_security', 'Can change security setting'), - ('change_clean', 'Can change clean setting'), - ('change_interface', 'Can change interface setting'), - ('change_license', 'Can change license setting'), - ('change_terminal', 'Can change terminal setting'), - ('change_other', 'Can change other setting') - ], 'verbose_name': 'System setting'}, - ), - ] diff --git a/apps/settings/migrations/0011_chatprompt.py b/apps/settings/migrations/0011_chatprompt.py deleted file mode 100644 index 1e2b05801..000000000 --- a/apps/settings/migrations/0011_chatprompt.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 4.1.10 on 2023-12-13 11:07 - -import uuid - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('settings', '0010_alter_setting_options'), - ] - - operations = [ - migrations.CreateModel( - name='ChatPrompt', - 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')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('content', models.TextField(verbose_name='Content')), - ('builtin', models.BooleanField(default=False, verbose_name='Builtin')), - ], - options={ - 'verbose_name': 'Chat prompt', - }, - ), - ] diff --git a/apps/settings/migrations/0012_alter_setting_options.py b/apps/settings/migrations/0012_alter_setting_options.py deleted file mode 100644 index f35da135f..000000000 --- a/apps/settings/migrations/0012_alter_setting_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 4.1.10 on 2023-12-20 07:51 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('settings', '0011_chatprompt'), - ] - - operations = [ - migrations.AlterModelOptions( - name='setting', - options={'permissions': [('change_email', 'Can change email setting'), ('change_auth', 'Can change auth setting'), ('change_ops', 'Can change auth ops'), ('change_ticket', 'Can change auth ticket'), ('change_virtualapp', 'Can change virtual app setting'), ('change_announcement', 'Can change auth announcement'), ('change_vault', 'Can change vault setting'), ('change_chatai', 'Can change chat ai setting'), ('change_systemmsgsubscription', 'Can change system msg sub setting'), ('change_sms', 'Can change sms setting'), ('change_security', 'Can change security setting'), ('change_clean', 'Can change clean setting'), ('change_interface', 'Can change interface setting'), ('change_license', 'Can change license setting'), ('change_terminal', 'Can change terminal setting'), ('change_other', 'Can change other setting')], 'verbose_name': 'System setting'}, - ), - ] diff --git a/apps/settings/migrations/0013_auto_20240326_1531.py b/apps/settings/migrations/0013_auto_20240326_1531.py deleted file mode 100644 index 59e6a7f34..000000000 --- a/apps/settings/migrations/0013_auto_20240326_1531.py +++ /dev/null @@ -1,42 +0,0 @@ -# Generated by Django 4.1.13 on 2024-03-26 07:31 -import json - -from django.db import migrations -from django.db.models import F - - -def migrate_feishu_to_lark(apps, schema_editor): - setting_model = apps.get_model("settings", "Setting") - user_model = apps.get_model("users", "User") - db_alias = schema_editor.connection.alias - - feishu_version_instance = setting_model.objects.using(db_alias).filter(name='FEISHU_VERSION').first() - if not feishu_version_instance or json.loads(feishu_version_instance.value) == 'feishu': - return - feishu_version_instance.delete() - - user_model.objects.using(db_alias).filter(feishu_id__isnull=False).update(lark_id=F('feishu_id')) - user_model.objects.filter(feishu_id__isnull=False).update(lark_id=F('feishu_id')) - user_model.objects.filter(feishu_id__isnull=False).update(feishu_id=None) - - settings_to_update = [ - ('AUTH_FEISHU', 'AUTH_LARK'), - ('FEISHU_APP_ID', 'LARK_APP_ID'), - ('FEISHU_APP_SECRET', 'LARK_APP_SECRET'), - ] - - for old_name, new_name in settings_to_update: - setting_model.objects.using(db_alias).filter( - name=old_name - ).update(name=new_name) - - -class Migration(migrations.Migration): - dependencies = [ - ('settings', '0012_alter_setting_options'), - ('users', '0050_user_lark_id_alter_user_source'), - ] - - operations = [ - migrations.RunPython(migrate_feishu_to_lark), - ] diff --git a/apps/terminal/migrations/0001_initial.py b/apps/terminal/migrations/0001_initial.py index 83d0fb1bc..e3b9eb630 100644 --- a/apps/terminal/migrations/0001_initial.py +++ b/apps/terminal/migrations/0001_initial.py @@ -1,54 +1,305 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2017-12-24 15:21 -from __future__ import unicode_literals - -import uuid +# Generated by Django 4.1.13 on 2024-05-09 03:16 +import common.db.fields +import django.core.validators from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import terminal.models.component.terminal +import uuid class Migration(migrations.Migration): + initial = True dependencies = [ + ('assets', '0001_initial'), ] operations = [ + migrations.CreateModel( + name='Applet', + 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)), + ('name', models.SlugField(max_length=128, unique=True, verbose_name='Name')), + ('display_name', models.CharField(max_length=128, verbose_name='Display name')), + ('version', models.CharField(max_length=16, verbose_name='Version')), + ('author', models.CharField(max_length=128, verbose_name='Author')), + ('edition', models.CharField(choices=[('community', 'Community edition'), ('enterprise', 'Enterprise')], default='community', max_length=128, verbose_name='Edition')), + ('type', models.CharField(choices=[('general', 'General'), ('web', 'Web')], default='general', max_length=16, verbose_name='Type')), + ('is_active', models.BooleanField(default=True, verbose_name='Is active')), + ('builtin', models.BooleanField(default=False, verbose_name='Builtin')), + ('protocols', models.JSONField(default=list, verbose_name='Protocol')), + ('can_concurrent', models.BooleanField(default=False, verbose_name='Can concurrent')), + ('tags', models.JSONField(default=list, verbose_name='Tags')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ], + options={ + 'verbose_name': 'Applet', + }, + ), + migrations.CreateModel( + name='AppletHost', + fields=[ + ('host_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='assets.host')), + ('deploy_options', models.JSONField(default=dict, verbose_name='Deploy options')), + ('auto_create_accounts', models.BooleanField(default=True, verbose_name='Auto create accounts')), + ('accounts_create_amount', models.IntegerField(default=100, verbose_name='Accounts create amount')), + ('inited', models.BooleanField(default=False, verbose_name='Inited')), + ('date_inited', models.DateTimeField(blank=True, null=True, verbose_name='Date inited')), + ('date_synced', models.DateTimeField(blank=True, null=True, verbose_name='Date synced')), + ('using_same_account', models.BooleanField(default=False, verbose_name='Using same account')), + ], + options={ + 'verbose_name': 'Hosting', + }, + bases=('assets.host',), + ), + migrations.CreateModel( + name='AppletHostDeployment', + 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)), + ('initial', models.BooleanField(default=False, verbose_name='Initial')), + ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), + ('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')), + ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('task', models.UUIDField(null=True, verbose_name='Task')), + ], + options={ + 'ordering': ('-date_start',), + }, + ), + migrations.CreateModel( + name='AppletPublication', + 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)), + ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ], + ), + migrations.CreateModel( + name='AppProvider', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('hostname', models.CharField(max_length=128, verbose_name='Hostname')), + ], + options={ + 'ordering': ('-date_created',), + }, + ), migrations.CreateModel( name='Command', fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('user', models.CharField(max_length=64, verbose_name='User')), - ('asset', models.CharField(max_length=128, verbose_name='Asset')), - ('system_user', models.CharField(max_length=64, verbose_name='System user')), + ('user', models.CharField(db_index=True, max_length=64, verbose_name='User')), + ('asset', models.CharField(db_index=True, max_length=128, verbose_name='Asset')), + ('account', models.CharField(db_index=True, max_length=64, verbose_name='Account')), ('input', models.CharField(db_index=True, max_length=128, verbose_name='Input')), ('output', models.CharField(blank=True, max_length=1024, verbose_name='Output')), ('session', models.CharField(db_index=True, max_length=36, verbose_name='Session')), + ('risk_level', models.SmallIntegerField(choices=[(0, 'Accept'), (4, 'Warning'), (5, 'Reject'), (6, 'Review & Reject'), (7, 'Review & Accept'), (8, 'Review & Cancel')], db_index=True, default=0, verbose_name='Risk level')), ('timestamp', models.IntegerField(db_index=True)), ], options={ + 'verbose_name': 'Command record', 'db_table': 'terminal_command', 'ordering': ('-timestamp',), }, ), migrations.CreateModel( - name='Session', + name='CommandStorage', 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('user', models.CharField(max_length=128, verbose_name='User')), - ('asset', models.CharField(max_length=1024, verbose_name='Asset')), - ('system_user', models.CharField(max_length=128, verbose_name='System user')), - ('login_from', models.CharField(choices=[('ST', 'SSH Terminal'), ('WT', 'Web Terminal')], default='ST', - max_length=2)), - ('is_finished', models.BooleanField(default=False)), - ('has_replay', models.BooleanField(default=False, verbose_name='Replay')), - ('has_command', models.BooleanField(default=False, verbose_name='Command')), - ('date_start', models.DateTimeField(verbose_name='Date start')), - ('date_end', models.DateTimeField(null=True, verbose_name='Date end')), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('meta', common.db.fields.EncryptJsonDictTextField(default={})), + ('is_default', models.BooleanField(default=False, verbose_name='Default storage')), + ('type', models.CharField(choices=[('null', 'Null'), ('server', 'Server'), ('es', 'Elasticsearch')], default='server', max_length=16, verbose_name='Type')), ], options={ + 'verbose_name': 'Command storage', + }, + ), + migrations.CreateModel( + name='Endpoint', + 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)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('host', models.CharField(blank=True, max_length=256, verbose_name='Host')), + ('https_port', common.db.fields.PortField(default=443, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='HTTPS port')), + ('http_port', common.db.fields.PortField(default=80, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='HTTP port')), + ('ssh_port', common.db.fields.PortField(default=2222, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='SSH port')), + ('rdp_port', common.db.fields.PortField(default=3389, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='RDP port')), + ('mysql_port', common.db.fields.PortField(default=33061, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='MySQL port')), + ('mariadb_port', common.db.fields.PortField(default=33062, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='MariaDB port')), + ('postgresql_port', common.db.fields.PortField(default=54320, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='PostgreSQL port')), + ('redis_port', common.db.fields.PortField(default=63790, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='Redis port')), + ('sqlserver_port', common.db.fields.PortField(default=14330, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='SQLServer port')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ], + options={ + 'verbose_name': 'Endpoint', + 'ordering': ('name',), + }, + ), + migrations.CreateModel( + name='EndpointRule', + 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)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('ip_group', models.JSONField(default=list, verbose_name='IP group')), + ('priority', models.IntegerField(help_text='1-100, the lower the value will be match first', unique=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('is_active', models.BooleanField(default=True, verbose_name='Is active')), + ], + options={ + 'verbose_name': 'Endpoint rule', + 'ordering': ('priority', 'is_active', 'name'), + }, + ), + migrations.CreateModel( + name='ReplayStorage', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('meta', common.db.fields.EncryptJsonDictTextField(default={})), + ('is_default', models.BooleanField(default=False, verbose_name='Default storage')), + ('type', models.CharField(choices=[('null', 'Null'), ('server', 'Server'), ('s3', 'S3'), ('ceph', 'Ceph'), ('swift', 'Swift'), ('oss', 'OSS'), ('azure', 'Azure'), ('obs', 'OBS'), ('cos', 'COS'), ('sftp', 'SFTP')], default='server', max_length=16, verbose_name='Type')), + ], + options={ + 'verbose_name': 'Replay storage', + }, + ), + migrations.CreateModel( + name='Session', + fields=[ + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('user', models.CharField(db_index=True, max_length=128, verbose_name='User')), + ('user_id', models.CharField(blank=True, db_index=True, default='', max_length=36)), + ('asset', models.CharField(db_index=True, max_length=128, verbose_name='Asset')), + ('asset_id', models.CharField(blank=True, db_index=True, default='', max_length=36)), + ('account', models.CharField(db_index=True, max_length=128, verbose_name='Account')), + ('account_id', models.CharField(db_index=True, max_length=128, verbose_name='Account id')), + ('protocol', models.CharField(db_index=True, default='ssh', max_length=16)), + ('login_from', models.CharField(choices=[('ST', 'SSH Terminal'), ('RT', 'RDP Terminal'), ('WT', 'Web Terminal'), ('DT', 'DB Terminal')], default='ST', max_length=2, verbose_name='Login from')), + ('type', models.CharField(db_index=True, default='normal', max_length=16)), + ('remote_addr', models.CharField(blank=True, max_length=128, null=True, verbose_name='Remote addr')), + ('is_success', models.BooleanField(db_index=True, default=True)), + ('is_finished', models.BooleanField(db_index=True, default=False)), + ('has_replay', models.BooleanField(default=False, verbose_name='Replay')), + ('has_command', models.BooleanField(default=False, verbose_name='Command')), + ('date_start', models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date start')), + ('date_end', models.DateTimeField(null=True, verbose_name='Date end')), + ('comment', models.TextField(blank=True, null=True, verbose_name='Comment')), + ('cmd_amount', models.IntegerField(default=-1, verbose_name='Command amount')), + ('error_reason', models.CharField(blank=True, max_length=128, verbose_name='Error reason')), + ], + options={ + 'verbose_name': 'Session record', 'db_table': 'terminal_session', 'ordering': ['-date_start'], + 'permissions': [('monitor_session', 'Can monitor session'), ('share_session', 'Can share session'), ('terminate_session', 'Can terminate session'), ('validate_sessionactionperm', 'Can validate session action perm')], + }, + ), + migrations.CreateModel( + name='SessionJoinRecord', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('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')), + ('verify_code', models.CharField(max_length=16, verbose_name='Verify code')), + ('date_joined', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Date joined')), + ('date_left', models.DateTimeField(db_index=True, null=True, verbose_name='Date left')), + ('remote_addr', models.CharField(blank=True, db_index=True, max_length=128, null=True, verbose_name='Remote addr')), + ('login_from', models.CharField(choices=[('ST', 'SSH Terminal'), ('RT', 'RDP Terminal'), ('WT', 'Web Terminal'), ('DT', 'DB Terminal')], default='WT', max_length=2, verbose_name='Login from')), + ('is_success', models.BooleanField(db_index=True, default=True, verbose_name='Success')), + ('reason', models.CharField(blank=True, default='-', max_length=1024, null=True, verbose_name='Reason')), + ('is_finished', models.BooleanField(db_index=True, default=False, verbose_name='Finished')), + ], + options={ + 'verbose_name': 'Session join record', + 'ordering': ('-date_joined',), + }, + ), + migrations.CreateModel( + name='SessionReplay', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ], + options={ + 'verbose_name': 'Session replay', + 'permissions': [('upload_sessionreplay', 'Can upload session replay'), ('download_sessionreplay', 'Can download session replay')], + }, + ), + migrations.CreateModel( + name='SessionSharing', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('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')), + ('verify_code', models.CharField(max_length=16, verbose_name='Verify code')), + ('is_active', models.BooleanField(db_index=True, default=True, verbose_name='Active')), + ('expired_time', models.IntegerField(db_index=True, default=0, verbose_name='Expired time (min)')), + ('users', models.TextField(blank=True, verbose_name='User')), + ('action_permission', models.CharField(default='writable', max_length=16, verbose_name='Action permission')), + ('origin', models.URLField(blank=True, null=True, verbose_name='Origin')), + ], + options={ + 'verbose_name': 'Session sharing', + 'ordering': ('-date_created',), + 'permissions': [('add_supersessionsharing', 'Can add super session sharing')], }, ), migrations.CreateModel( @@ -56,14 +307,16 @@ class Migration(migrations.Migration): fields=[ ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('session_online', models.IntegerField(default=0, verbose_name='Session Online')), - ('cpu_used', models.FloatField(verbose_name='CPU Usage')), + ('cpu_load', models.FloatField(default=0, verbose_name='CPU Load')), ('memory_used', models.FloatField(verbose_name='Memory Used')), - ('connections', models.IntegerField(verbose_name='Connections')), - ('threads', models.IntegerField(verbose_name='Threads')), - ('boot_time', models.FloatField(verbose_name='Boot Time')), + ('disk_used', models.FloatField(default=0, verbose_name='Disk Used')), + ('connections', models.IntegerField(default=0, verbose_name='Connections')), + ('threads', models.IntegerField(default=0, verbose_name='Threads')), + ('boot_time', models.FloatField(default=0, verbose_name='Boot Time')), ('date_created', models.DateTimeField(auto_now_add=True)), ], options={ + 'verbose_name': 'Status', 'db_table': 'terminal_status', 'get_latest_by': 'date_created', }, @@ -71,34 +324,90 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Task', 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', - models.CharField(choices=[('kill_session', 'Kill Session')], max_length=128, verbose_name='Name')), + ('name', models.CharField(choices=[('kill_session', 'Kill session'), ('lock_session', 'Lock session'), ('unlock_session', 'Unlock session')], max_length=128, verbose_name='Name')), ('args', models.CharField(max_length=1024, verbose_name='Args')), + ('kwargs', models.JSONField(default=dict, verbose_name='Kwargs')), ('is_finished', models.BooleanField(default=False)), - ('date_created', models.DateTimeField(auto_now_add=True)), ('date_finished', models.DateTimeField(null=True)), ], options={ + 'verbose_name': 'Task', 'db_table': 'terminal_task', }, ), migrations.CreateModel( name='Terminal', 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=32, unique=True, verbose_name='Name')), - ('remote_addr', models.CharField(max_length=128, verbose_name='Remote Address')), - ('ssh_port', models.IntegerField(default=2222, verbose_name='SSH port')), - ('http_port', models.IntegerField(default=5000, verbose_name='HTTP port')), - ('is_accepted', models.BooleanField(default=False, verbose_name='Is Accepted')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('type', models.CharField(choices=[('koko', 'KoKo'), ('guacamole', 'Guacamole'), ('omnidb', 'OmniDB'), ('xrdp', 'Xrdp'), ('lion', 'Lion'), ('core', 'Core'), ('celery', 'Celery'), ('magnus', 'Magnus'), ('razor', 'Razor'), ('tinker', 'Tinker'), ('video_worker', 'Video Worker'), ('chen', 'Chen'), ('kael', 'Kael'), ('panda', 'Panda')], default='koko', max_length=64, verbose_name='type')), + ('remote_addr', models.CharField(blank=True, max_length=128, verbose_name='Remote Address')), + ('command_storage', models.CharField(default='default', max_length=128, verbose_name='Command storage')), + ('replay_storage', models.CharField(default='default', max_length=128, verbose_name='Replay storage')), ('is_deleted', models.BooleanField(default=False)), - ('date_created', models.DateTimeField(auto_now_add=True)), - ('comment', models.TextField(blank=True, verbose_name='Comment')), ], options={ + 'verbose_name': 'Terminal', 'db_table': 'terminal', - 'ordering': ('is_accepted',), + 'permissions': (('view_terminalconfig', 'Can view terminal config'),), + }, + bases=(terminal.models.component.terminal.StorageMixin, terminal.models.component.terminal.TerminalStatusMixin, models.Model), + ), + migrations.CreateModel( + name='VirtualApp', + 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)), + ('name', models.SlugField(max_length=128, unique=True, verbose_name='Name')), + ('display_name', models.CharField(max_length=128, verbose_name='Display name')), + ('version', models.CharField(max_length=16, verbose_name='Version')), + ('author', models.CharField(max_length=128, verbose_name='Author')), + ('is_active', models.BooleanField(default=True, verbose_name='Is active')), + ('protocols', models.JSONField(default=list, verbose_name='Protocol')), + ('image_name', models.CharField(max_length=128, verbose_name='Image name')), + ('image_protocol', models.CharField(default='vnc', max_length=16, verbose_name='Image protocol')), + ('image_port', models.IntegerField(default=5900, verbose_name='Image port')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('tags', models.JSONField(default=list, verbose_name='Tags')), + ], + options={ + 'verbose_name': 'Virtual app', }, ), + migrations.CreateModel( + name='VirtualAppPublication', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), + ('app', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publications', to='terminal.virtualapp', verbose_name='Virtual app')), + ('provider', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publications', to='terminal.appprovider', verbose_name='App Provider')), + ], + options={ + 'verbose_name': 'Virtual app publication', + }, + ), + migrations.AddField( + model_name='virtualapp', + name='providers', + field=models.ManyToManyField(through='terminal.VirtualAppPublication', to='terminal.appprovider', verbose_name='Providers'), + ), ] diff --git a/apps/terminal/migrations/0002_auto_20171228_0025.py b/apps/terminal/migrations/0002_auto_20171228_0025.py index 15ef50195..39141ccb2 100644 --- a/apps/terminal/migrations/0002_auto_20171228_0025.py +++ b/apps/terminal/migrations/0002_auto_20171228_0025.py @@ -1,6 +1,4 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2017-12-27 16:25 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 from django.conf import settings from django.db import migrations, models @@ -9,35 +7,115 @@ import django.db.models.deletion class Migration(migrations.Migration): + initial = True + dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('terminal', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.AddField( - model_name='session', - name='terminal', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='terminal.Terminal'), - ), - migrations.AddField( - model_name='status', - name='terminal', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='terminal.Terminal'), - ), - migrations.AddField( - model_name='task', - name='terminal', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='terminal.Terminal'), - ), migrations.AddField( model_name='terminal', name='user', field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='terminal', to=settings.AUTH_USER_MODEL, verbose_name='Application User'), ), - migrations.AlterField( - model_name='terminal', - name='name', - field=models.CharField(max_length=32, verbose_name='Name'), + migrations.AddField( + model_name='task', + name='terminal', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='terminal.terminal'), + ), + migrations.AddField( + model_name='status', + name='terminal', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='terminal.terminal'), + ), + migrations.AddField( + model_name='sessionsharing', + name='creator', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Creator'), + ), + migrations.AddField( + model_name='sessionsharing', + name='session', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.session', verbose_name='Session'), + ), + migrations.AddField( + model_name='sessionreplay', + name='session', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.session', verbose_name='Session'), + ), + migrations.AddField( + model_name='sessionjoinrecord', + name='joiner', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Joiner'), + ), + migrations.AddField( + model_name='sessionjoinrecord', + name='session', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.session', verbose_name='Session'), + ), + migrations.AddField( + model_name='sessionjoinrecord', + name='sharing', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.sessionsharing', verbose_name='Session sharing'), + ), + migrations.AddField( + model_name='session', + name='terminal', + field=models.ForeignKey(db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='terminal.terminal'), + ), + migrations.AddField( + model_name='endpointrule', + name='endpoint', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rules', to='terminal.endpoint', verbose_name='Endpoint'), + ), + migrations.AddField( + model_name='appprovider', + name='apps', + field=models.ManyToManyField(through='terminal.VirtualAppPublication', to='terminal.virtualapp', verbose_name='Virtual app'), + ), + migrations.AddField( + model_name='appprovider', + name='terminal', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='app_provider', to='terminal.terminal', verbose_name='Terminal'), + ), + migrations.AddField( + model_name='appletpublication', + name='applet', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publications', to='terminal.applet', verbose_name='Applet'), + ), + migrations.AddField( + model_name='appletpublication', + name='host', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publications', to='terminal.applethost', verbose_name='Hosting'), + ), + migrations.AddField( + model_name='applethostdeployment', + name='host', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.applethost', verbose_name='Hosting'), + ), + migrations.AddField( + model_name='applethost', + name='applets', + field=models.ManyToManyField(through='terminal.AppletPublication', to='terminal.applet', verbose_name='Applet'), + ), + migrations.AddField( + model_name='applethost', + name='terminal', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='applet_host', to='terminal.terminal', verbose_name='Terminal'), + ), + migrations.AddField( + model_name='applet', + name='hosts', + field=models.ManyToManyField(through='terminal.AppletPublication', to='terminal.applethost', verbose_name='Hosts'), + ), + migrations.AlterUniqueTogether( + name='virtualapppublication', + unique_together={('provider', 'app')}, + ), + migrations.AlterUniqueTogether( + name='appletpublication', + unique_together={('applet', 'host')}, ), ] diff --git a/apps/terminal/migrations/0003_auto_20171230_0308.py b/apps/terminal/migrations/0003_auto_20171230_0308.py deleted file mode 100644 index 35a8b3138..000000000 --- a/apps/terminal/migrations/0003_auto_20171230_0308.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2017-12-29 19:08 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0002_auto_20171228_0025'), - ] - - operations = [ - migrations.AlterField( - model_name='command', - name='asset', - field=models.CharField(db_index=True, max_length=128, verbose_name='Asset'), - ), - migrations.AlterField( - model_name='command', - name='system_user', - field=models.CharField(db_index=True, max_length=64, verbose_name='System user'), - ), - migrations.AlterField( - model_name='command', - name='user', - field=models.CharField(db_index=True, max_length=64, verbose_name='User'), - ), - ] diff --git a/apps/terminal/migrations/0004_session_remote_addr.py b/apps/terminal/migrations/0004_session_remote_addr.py deleted file mode 100644 index d5661c1d7..000000000 --- a/apps/terminal/migrations/0004_session_remote_addr.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-05 10:07 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0003_auto_20171230_0308'), - ] - - operations = [ - migrations.AddField( - model_name='session', - name='remote_addr', - field=models.CharField(blank=True, max_length=15, null=True, verbose_name='Remote addr'), - ), - ] diff --git a/apps/terminal/migrations/0005_auto_20180122_1154.py b/apps/terminal/migrations/0005_auto_20180122_1154.py deleted file mode 100644 index 4a6b18709..000000000 --- a/apps/terminal/migrations/0005_auto_20180122_1154.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-22 03:54 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0004_session_remote_addr'), - ] - - operations = [ - migrations.AddField( - model_name='terminal', - name='command_storage', - field=models.CharField(choices=[('default', 'default'), ('elk', 'elk')], default='default', max_length=128, verbose_name='Command storage'), - ), - migrations.AddField( - model_name='terminal', - name='replay_storage', - field=models.CharField(default='default', max_length=128, verbose_name='Replay storage'), - ), - ] diff --git a/apps/terminal/migrations/0006_auto_20180123_1037.py b/apps/terminal/migrations/0006_auto_20180123_1037.py deleted file mode 100644 index 1090ac3bf..000000000 --- a/apps/terminal/migrations/0006_auto_20180123_1037.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-23 02:37 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0005_auto_20180122_1154'), - ] - - operations = [ - migrations.AlterField( - model_name='terminal', - name='command_storage', - field=models.CharField(default='default', max_length=128, verbose_name='Command storage'), - ), - ] diff --git a/apps/terminal/migrations/0007_session_date_last_active.py b/apps/terminal/migrations/0007_session_date_last_active.py deleted file mode 100644 index 3392f2617..000000000 --- a/apps/terminal/migrations/0007_session_date_last_active.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-02-27 09:13 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.utils.timezone - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0006_auto_20180123_1037'), - ] - - operations = [ - migrations.AddField( - model_name='session', - name='date_last_active', - field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Date last active'), - ), - ] diff --git a/apps/terminal/migrations/0008_auto_20180307_1603.py b/apps/terminal/migrations/0008_auto_20180307_1603.py deleted file mode 100644 index 9ef64393c..000000000 --- a/apps/terminal/migrations/0008_auto_20180307_1603.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-03-07 08:03 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0007_session_date_last_active'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='date_start', - field=models.DateTimeField(db_index=True, verbose_name='Date start'), - ), - ] diff --git a/apps/terminal/migrations/0009_auto_20180326_0957.py b/apps/terminal/migrations/0009_auto_20180326_0957.py deleted file mode 100644 index 301ab00a2..000000000 --- a/apps/terminal/migrations/0009_auto_20180326_0957.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-03-26 01:57 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0008_auto_20180307_1603'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='terminal', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='terminal.Terminal'), - ), - migrations.AlterField( - model_name='task', - name='terminal', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='terminal.Terminal'), - ), - ] diff --git a/apps/terminal/migrations/0010_auto_20180423_1140.py b/apps/terminal/migrations/0010_auto_20180423_1140.py deleted file mode 100644 index d365d0c49..000000000 --- a/apps/terminal/migrations/0010_auto_20180423_1140.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-23 03:40 -from __future__ import unicode_literals - -from django.db import migrations, models -import django.utils.timezone - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0009_auto_20180326_0957'), - ] - - operations = [ - migrations.AddField( - model_name='session', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp')], default='ssh', max_length=8), - ), - migrations.AlterField( - model_name='session', - name='date_start', - field=models.DateTimeField(db_index=True, default=django.utils.timezone.now, verbose_name='Date start'), - ), - ] diff --git a/apps/terminal/migrations/0011_auto_20180807_1116.py b/apps/terminal/migrations/0011_auto_20180807_1116.py deleted file mode 100644 index acf3404b9..000000000 --- a/apps/terminal/migrations/0011_auto_20180807_1116.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.0.7 on 2018-08-07 03:16 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0010_auto_20180423_1140'), - ] - - operations = [ - migrations.AddField( - model_name='command', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AddField( - model_name='session', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - ] diff --git a/apps/terminal/migrations/0012_auto_20180816_1652.py b/apps/terminal/migrations/0012_auto_20180816_1652.py deleted file mode 100644 index 50c43574c..000000000 --- a/apps/terminal/migrations/0012_auto_20180816_1652.py +++ /dev/null @@ -1,13 +0,0 @@ -# Generated by Django 2.0.7 on 2018-08-16 08:52 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0011_auto_20180807_1116'), - ] - - operations = [ - ] diff --git a/apps/terminal/migrations/0013_auto_20181123_1113.py b/apps/terminal/migrations/0013_auto_20181123_1113.py deleted file mode 100644 index 9ecff3416..000000000 --- a/apps/terminal/migrations/0013_auto_20181123_1113.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.1 on 2018-11-23 03:13 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0012_auto_20180816_1652'), - ] - - operations = [ - migrations.AlterField( - model_name='terminal', - name='remote_addr', - field=models.CharField(blank=True, max_length=128, verbose_name='Remote Address'), - ), - ] diff --git a/apps/terminal/migrations/0014_auto_20181226_1441.py b/apps/terminal/migrations/0014_auto_20181226_1441.py deleted file mode 100644 index fa890365a..000000000 --- a/apps/terminal/migrations/0014_auto_20181226_1441.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1 on 2018-12-26 06:41 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0013_auto_20181123_1113'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc')], default='ssh', max_length=8), - ), - ] diff --git a/apps/terminal/migrations/0015_auto_20190923_1529.py b/apps/terminal/migrations/0015_auto_20190923_1529.py deleted file mode 100644 index 9c52d42d2..000000000 --- a/apps/terminal/migrations/0015_auto_20190923_1529.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-09-23 07:29 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0014_auto_20181226_1441'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc'), ('telnet', 'telnet')], default='ssh', max_length=8), - ), - ] diff --git a/apps/terminal/migrations/0016_commandstorage_replaystorage.py b/apps/terminal/migrations/0016_commandstorage_replaystorage.py deleted file mode 100644 index 5eb17046a..000000000 --- a/apps/terminal/migrations/0016_commandstorage_replaystorage.py +++ /dev/null @@ -1,52 +0,0 @@ -# Generated by Django 2.2.5 on 2019-11-22 10:07 - -import uuid - -from django.db import migrations, models - -import common.db.fields - - -class Migration(migrations.Migration): - dependencies = [ - ('terminal', '0015_auto_20190923_1529'), - ] - - operations = [ - migrations.CreateModel( - name='CommandStorage', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('name', models.CharField(max_length=32, unique=True, verbose_name='Name')), - ('type', models.CharField(choices=[('null', 'Null'), ('server', 'Server'), ('es', 'Elasticsearch')], - default='server', max_length=16, verbose_name='Type')), - ('meta', common.db.fields.EncryptJsonDictTextField(default={})), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ], - options={ - 'abstract': False, - }, - ), - migrations.CreateModel( - name='ReplayStorage', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('name', models.CharField(max_length=32, unique=True, verbose_name='Name')), - ('type', models.CharField( - choices=[('null', 'Null'), ('server', 'Server'), ('s3', 'S3'), ('ceph', 'Ceph'), ('swift', 'Swift'), - ('oss', 'OSS'), ('azure', 'Azure')], default='server', max_length=16, - verbose_name='Type')), - ('meta', common.db.fields.EncryptJsonDictTextField(default={})), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ], - options={ - 'abstract': False, - }, - ), - ] diff --git a/apps/terminal/migrations/0017_auto_20191125_0931.py b/apps/terminal/migrations/0017_auto_20191125_0931.py deleted file mode 100644 index ad6267c39..000000000 --- a/apps/terminal/migrations/0017_auto_20191125_0931.py +++ /dev/null @@ -1,88 +0,0 @@ -# Generated by Django 2.2.5 on 2019-11-25 01:31 - -from django.db import migrations - - -def get_storage_data(s): - from common.utils import signer - import json - value = s.value - encrypted = s.encrypted - if encrypted: - value = signer.unsign(value) - try: - value = json.loads(value) - except: - value = {} - return value - - -def get_setting(apps, schema_editor, key): - model = apps.get_model('settings', 'Setting') - db_alias = schema_editor.connection.alias - setting = model.objects.using(db_alias).filter(name=key) - if not setting: - return - return setting[0] - - -def init_storage_data(model): - model.objects.update_or_create( - name='null', type='null', - defaults={ - 'name': 'null', 'type': 'null', - 'comment': "Do not save", - 'meta': '{}' - } - ) - model.objects.update_or_create( - name='default', type='server', - defaults={ - 'name': 'default', 'type': 'server', - 'comment': "Store locally", - 'meta': '{}' - } - ) - - -def migrate_command_storage(apps, schema_editor): - model = apps.get_model("terminal", "CommandStorage") - init_storage_data(model) - - setting = get_setting(apps, schema_editor, "TERMINAL_COMMAND_STORAGE") - if not setting: - return - values = get_storage_data(setting) - for name, meta in values.items(): - tp = meta.pop("TYPE") - if not tp or name in ['default', 'null']: - continue - print("- command storage Meta: ", meta) - model.objects.create(name=name, type=tp, meta=meta) - - -def migrate_replay_storage(apps, schema_editor): - model = apps.get_model("terminal", "ReplayStorage") - init_storage_data(model) - - setting = get_setting(apps, schema_editor, "TERMINAL_REPLAY_STORAGE") - if not setting: - return - values = get_storage_data(setting) - for name, meta in values.items(): - tp = meta.pop("TYPE", None) - if not tp or name in ['default', 'null']: - continue - model.objects.create(name=name, type=tp, meta=meta) - - -class Migration(migrations.Migration): - dependencies = [ - ('settings', '0001_initial'), - ('terminal', '0016_commandstorage_replaystorage'), - ] - - operations = [ - migrations.RunPython(migrate_command_storage), - migrations.RunPython(migrate_replay_storage), - ] diff --git a/apps/terminal/migrations/0018_auto_20191202_1010.py b/apps/terminal/migrations/0018_auto_20191202_1010.py deleted file mode 100644 index f121db2b5..000000000 --- a/apps/terminal/migrations/0018_auto_20191202_1010.py +++ /dev/null @@ -1,67 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-02 02:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0017_auto_20191125_0931'), - ] - - operations = [ - migrations.RemoveField( - model_name='session', - name='date_last_active', - ), - migrations.AlterField( - model_name='session', - name='remote_addr', - field=models.CharField(blank=True, max_length=128, null=True, - verbose_name='Remote addr'), - ), - migrations.AddField( - model_name='session', - name='asset_id', - field=models.CharField(blank=True, db_index=True, default='', - max_length=36), - ), - migrations.AddField( - model_name='session', - name='system_user_id', - field=models.CharField(blank=True, db_index=True, default='', - max_length=36), - ), - migrations.AddField( - model_name='session', - name='user_id', - field=models.CharField(blank=True, db_index=True, default='', - max_length=36), - ), - migrations.AlterField( - model_name='session', - name='asset', - field=models.CharField(db_index=True, max_length=128, - verbose_name='Asset'), - ), - migrations.AlterField( - model_name='session', - name='protocol', - field=models.CharField( - choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc'), - ('telnet', 'telnet')], db_index=True, default='ssh', - max_length=8), - ), - migrations.AlterField( - model_name='session', - name='system_user', - field=models.CharField(db_index=True, max_length=128, - verbose_name='System user'), - ), - migrations.AlterField( - model_name='session', - name='user', - field=models.CharField(db_index=True, max_length=128, - verbose_name='User'), - ), - ] diff --git a/apps/terminal/migrations/0019_auto_20191206_1000.py b/apps/terminal/migrations/0019_auto_20191206_1000.py deleted file mode 100644 index 069920085..000000000 --- a/apps/terminal/migrations/0019_auto_20191206_1000.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.7 on 2019-12-06 02:00 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0018_auto_20191202_1010'), - ] - - operations = [ - migrations.AlterField( - model_name='replaystorage', - name='type', - field=models.CharField(choices=[('null', 'Null'), ('server', 'Server'), ('s3', 'S3'), ('ceph', 'Ceph'), ('swift', 'Swift'), ('oss', 'OSS'), ('azure', 'Azure')], default='server', max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/terminal/migrations/0020_auto_20191218_1721.py b/apps/terminal/migrations/0020_auto_20191218_1721.py deleted file mode 100644 index d9c6bfa5b..000000000 --- a/apps/terminal/migrations/0020_auto_20191218_1721.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.11 on 2019-12-18 09:21 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0019_auto_20191206_1000'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc'), ('telnet', 'telnet'), ('mysql', 'mysql')], db_index=True, default='ssh', max_length=8), - ), - ] diff --git a/apps/terminal/migrations/0021_auto_20200213_1316.py b/apps/terminal/migrations/0021_auto_20200213_1316.py deleted file mode 100644 index 7b1c62b38..000000000 --- a/apps/terminal/migrations/0021_auto_20200213_1316.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-02-13 05:16 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0020_auto_20191218_1721'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='is_finished', - field=models.BooleanField(db_index=True, default=False), - ), - ] diff --git a/apps/terminal/migrations/0022_session_is_success.py b/apps/terminal/migrations/0022_session_is_success.py deleted file mode 100644 index 72ef9b283..000000000 --- a/apps/terminal/migrations/0022_session_is_success.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-02-27 08:44 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0021_auto_20200213_1316'), - ] - - operations = [ - migrations.AddField( - model_name='session', - name='is_success', - field=models.BooleanField(db_index=True, default=True), - ), - ] diff --git a/apps/terminal/migrations/0023_command_risk_level.py b/apps/terminal/migrations/0023_command_risk_level.py deleted file mode 100644 index 0b5ed6bb6..000000000 --- a/apps/terminal/migrations/0023_command_risk_level.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-03-03 08:26 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0022_session_is_success'), - ] - - operations = [ - migrations.AddField( - model_name='command', - name='risk_level', - field=models.SmallIntegerField(choices=[(0, 'Accept'), (4, 'Warning'), (5, 'Reject'), (6, 'Review & Reject'), (7, 'Review & Accept'), (8, 'Review & Cancel')], db_index=True, default=0, verbose_name='Risk level'), - ), - ] diff --git a/apps/terminal/migrations/0024_auto_20200715_1713.py b/apps/terminal/migrations/0024_auto_20200715_1713.py deleted file mode 100644 index b99ad8d79..000000000 --- a/apps/terminal/migrations/0024_auto_20200715_1713.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-15 09:13 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0023_command_risk_level'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='login_from', - field=models.CharField(choices=[('ST', 'SSH Terminal'), ('WT', 'Web Terminal')], default='ST', max_length=2, verbose_name='Login from'), - ), - ] diff --git a/apps/terminal/migrations/0025_auto_20200810_1735.py b/apps/terminal/migrations/0025_auto_20200810_1735.py deleted file mode 100644 index 96a06915c..000000000 --- a/apps/terminal/migrations/0025_auto_20200810_1735.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-10 09:35 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0024_auto_20200715_1713'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc'), ('telnet', 'telnet'), ('mysql', 'mysql'), ('k8s', 'kubernetes')], db_index=True, default='ssh', max_length=8), - ), - ] diff --git a/apps/terminal/migrations/0026_auto_20201027_1905.py b/apps/terminal/migrations/0026_auto_20201027_1905.py deleted file mode 100644 index d820166d6..000000000 --- a/apps/terminal/migrations/0026_auto_20201027_1905.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-27 11:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0025_auto_20200810_1735'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc'), ('telnet', 'telnet'), ('mysql', 'mysql'), ('oracle', 'oracle'), ('mariadb', 'mariadb'), ('postgresql', 'postgresql'), ('k8s', 'kubernetes')], db_index=True, default='ssh', max_length=16), - ), - ] diff --git a/apps/terminal/migrations/0027_auto_20201102_1651.py b/apps/terminal/migrations/0027_auto_20201102_1651.py deleted file mode 100644 index 5a328d84a..000000000 --- a/apps/terminal/migrations/0027_auto_20201102_1651.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 2.2.13 on 2020-11-02 08:51 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0026_auto_20201027_1905'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='terminal', - field=models.ForeignKey(db_constraint=False, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='terminal.Terminal'), - ), - ] diff --git a/apps/terminal/migrations/0028_auto_20201110_1918.py b/apps/terminal/migrations/0028_auto_20201110_1918.py deleted file mode 100644 index 948bdde1a..000000000 --- a/apps/terminal/migrations/0028_auto_20201110_1918.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.13 on 2020-11-10 11:18 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0027_auto_20201102_1651'), - ] - - operations = [ - migrations.AlterField( - model_name='terminal', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - ] diff --git a/apps/terminal/migrations/0029_auto_20201116_1757.py b/apps/terminal/migrations/0029_auto_20201116_1757.py deleted file mode 100644 index 27b4c60b9..000000000 --- a/apps/terminal/migrations/0029_auto_20201116_1757.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.2.13 on 2020-11-16 09:57 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0028_auto_20201110_1918'), - ] - - operations = [ - migrations.AlterField( - model_name='commandstorage', - name='name', - field=models.CharField(max_length=128, unique=True, verbose_name='Name'), - ), - migrations.AlterField( - model_name='replaystorage', - name='name', - field=models.CharField(max_length=128, unique=True, verbose_name='Name'), - ), - ] diff --git a/apps/terminal/migrations/0030_terminal_type.py b/apps/terminal/migrations/0030_terminal_type.py deleted file mode 100644 index 1ede3ec94..000000000 --- a/apps/terminal/migrations/0030_terminal_type.py +++ /dev/null @@ -1,41 +0,0 @@ -# Generated by Django 3.1 on 2020-12-15 04:52 - -from django.db import migrations, models - -TERMINAL_TYPE_KOKO = 'koko' -TERMINAL_TYPE_GUACAMOLE = 'guacamole' -TERMINAL_TYPE_OMNIDB = 'omnidb' - - -def migrate_terminal_type(apps, schema_editor): - terminal_model = apps.get_model("terminal", "Terminal") - db_alias = schema_editor.connection.alias - terminals = terminal_model.objects.using(db_alias).all() - for terminal in terminals: - name = terminal.name.lower() - if 'koko' in name: - _type = TERMINAL_TYPE_KOKO - elif 'gua' in name: - _type = TERMINAL_TYPE_GUACAMOLE - elif 'omnidb' in name: - _type = TERMINAL_TYPE_OMNIDB - else: - _type = TERMINAL_TYPE_KOKO - terminal.type = _type - terminal_model.objects.bulk_update(terminals, ['type']) - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0029_auto_20201116_1757'), - ] - - operations = [ - migrations.AddField( - model_name='terminal', - name='type', - field=models.CharField(choices=[('koko', 'KoKo'), ('guacamole', 'Guacamole'), ('omnidb', 'OmniDB')], default='koko', max_length=64, verbose_name='type'), - ), - migrations.RunPython(migrate_terminal_type) - ] diff --git a/apps/terminal/migrations/0031_auto_20210113_1356.py b/apps/terminal/migrations/0031_auto_20210113_1356.py deleted file mode 100644 index 6866b0c2a..000000000 --- a/apps/terminal/migrations/0031_auto_20210113_1356.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.1 on 2021-01-13 05:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0030_terminal_type'), - ] - - operations = [ - migrations.AlterField( - model_name='commandstorage', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='replaystorage', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - ] diff --git a/apps/terminal/migrations/0032_auto_20210302_1853.py b/apps/terminal/migrations/0032_auto_20210302_1853.py deleted file mode 100644 index df94e9b2a..000000000 --- a/apps/terminal/migrations/0032_auto_20210302_1853.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2021-03-02 10:53 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0031_auto_20210113_1356'), - ] - - operations = [ - migrations.AlterField( - model_name='terminal', - name='type', - field=models.CharField(choices=[('koko', 'KoKo'), ('guacamole', 'Guacamole'), ('omnidb', 'OmniDB'), ('xrdp', 'Xrdp')], default='koko', max_length=64, verbose_name='type'), - ), - ] diff --git a/apps/terminal/migrations/0033_auto_20210324_1008.py b/apps/terminal/migrations/0033_auto_20210324_1008.py deleted file mode 100644 index f5ecaf6d0..000000000 --- a/apps/terminal/migrations/0033_auto_20210324_1008.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2021-03-24 02:08 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0032_auto_20210302_1853'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='login_from', - field=models.CharField(choices=[('ST', 'SSH Terminal'), ('RT', 'RDP Terminal'), ('WT', 'Web Terminal')], default='ST', max_length=2, verbose_name='Login from'), - ), - ] diff --git a/apps/terminal/migrations/0034_auto_20210406_1434.py b/apps/terminal/migrations/0034_auto_20210406_1434.py deleted file mode 100644 index 59cc89b9b..000000000 --- a/apps/terminal/migrations/0034_auto_20210406_1434.py +++ /dev/null @@ -1,42 +0,0 @@ -# Generated by Django 3.1 on 2021-04-06 06:34 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0033_auto_20210324_1008'), - ] - - operations = [ - migrations.RemoveField( - model_name='status', - name='cpu_used', - ), - migrations.AddField( - model_name='status', - name='cpu_load', - field=models.FloatField(default=0, verbose_name='CPU Load'), - ), - migrations.AddField( - model_name='status', - name='disk_used', - field=models.FloatField(default=0, verbose_name='Disk Used'), - ), - migrations.AlterField( - model_name='status', - name='boot_time', - field=models.FloatField(default=0, verbose_name='Boot Time'), - ), - migrations.AlterField( - model_name='status', - name='connections', - field=models.IntegerField(default=0, verbose_name='Connections'), - ), - migrations.AlterField( - model_name='status', - name='threads', - field=models.IntegerField(default=0, verbose_name='Threads'), - ), - ] diff --git a/apps/terminal/migrations/0035_auto_20210517_1448.py b/apps/terminal/migrations/0035_auto_20210517_1448.py deleted file mode 100644 index 2c8592700..000000000 --- a/apps/terminal/migrations/0035_auto_20210517_1448.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.6 on 2021-05-17 06:48 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0034_auto_20210406_1434'), - ] - - operations = [ - migrations.AlterField( - model_name='terminal', - name='type', - field=models.CharField(choices=[('koko', 'KoKo'), ('guacamole', 'Guacamole'), ('omnidb', 'OmniDB'), ('xrdp', 'Xrdp'), ('lion', 'Lion')], default='koko', max_length=64, verbose_name='type'), - ), - ] diff --git a/apps/terminal/migrations/0036_auto_20210604_1124.py b/apps/terminal/migrations/0036_auto_20210604_1124.py deleted file mode 100644 index 31746dfba..000000000 --- a/apps/terminal/migrations/0036_auto_20210604_1124.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-04 03:24 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0035_auto_20210517_1448'), - ] - - operations = [ - migrations.AlterField( - model_name='replaystorage', - name='type', - field=models.CharField(choices=[('null', 'Null'), ('server', 'Server'), ('s3', 'S3'), ('ceph', 'Ceph'), ('swift', 'Swift'), ('oss', 'OSS'), ('azure', 'Azure'), ('obs', 'OBS')], default='server', max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/terminal/migrations/0037_auto_20210623_1748.py b/apps/terminal/migrations/0037_auto_20210623_1748.py deleted file mode 100644 index fde10b3b7..000000000 --- a/apps/terminal/migrations/0037_auto_20210623_1748.py +++ /dev/null @@ -1,37 +0,0 @@ -# Generated by Django 3.1.6 on 2021-06-23 09:48 - -from django.db import migrations, models - - -def set_default_storage(apps, schema_editor): - command_storage_model = apps.get_model("terminal", "CommandStorage") - command_storage = command_storage_model.objects.filter(name='default', type='server').first() - if command_storage: - command_storage.is_default = True - command_storage.save() - replay_storage_model = apps.get_model("terminal", "ReplayStorage") - replay_storage = replay_storage_model.objects.filter(name='default', type='server').first() - if replay_storage: - replay_storage.is_default = True - replay_storage.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0036_auto_20210604_1124'), - ] - - operations = [ - migrations.AddField( - model_name='commandstorage', - name='is_default', - field=models.BooleanField(default=False, verbose_name='Default storage'), - ), - migrations.AddField( - model_name='replaystorage', - name='is_default', - field=models.BooleanField(default=False, verbose_name='Default storage'), - ), - migrations.RunPython(set_default_storage) - ] diff --git a/apps/terminal/migrations/0038_task_kwargs.py b/apps/terminal/migrations/0038_task_kwargs.py deleted file mode 100644 index 389a5586b..000000000 --- a/apps/terminal/migrations/0038_task_kwargs.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.6 on 2021-07-29 06:06 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0037_auto_20210623_1748'), - ] - - operations = [ - migrations.AddField( - model_name='task', - name='kwargs', - field=models.JSONField(default=dict, verbose_name='Kwargs'), - ), - ] diff --git a/apps/terminal/migrations/0039_auto_20210805_1552.py b/apps/terminal/migrations/0039_auto_20210805_1552.py deleted file mode 100644 index 060e22548..000000000 --- a/apps/terminal/migrations/0039_auto_20210805_1552.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.6 on 2021-08-05 07:52 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0038_task_kwargs'), - ] - - operations = [ - migrations.AlterField( - model_name='terminal', - name='type', - field=models.CharField(choices=[('koko', 'KoKo'), ('guacamole', 'Guacamole'), ('omnidb', 'OmniDB'), ('xrdp', 'Xrdp'), ('lion', 'Lion'), ('core', 'Core'), ('celery', 'Celery')], default='koko', max_length=64, verbose_name='type'), - ), - ] diff --git a/apps/terminal/migrations/0040_sessionjoinrecord_sessionsharing.py b/apps/terminal/migrations/0040_sessionjoinrecord_sessionsharing.py deleted file mode 100644 index a2e0933a8..000000000 --- a/apps/terminal/migrations/0040_sessionjoinrecord_sessionsharing.py +++ /dev/null @@ -1,59 +0,0 @@ -# Generated by Django 3.1.12 on 2021-09-07 09:20 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('terminal', '0039_auto_20210805_1552'), - ] - - operations = [ - migrations.CreateModel( - name='SessionSharing', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('verify_code', models.CharField(max_length=16, verbose_name='Verify code')), - ('is_active', models.BooleanField(db_index=True, default=True, verbose_name='Active')), - ('expired_time', models.IntegerField(db_index=True, default=0, verbose_name='Expired time (min)')), - ('creator', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Creator')), - ('session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.session', verbose_name='Session')), - ], - options={ - 'ordering': ('-date_created',), - }, - ), - migrations.CreateModel( - name='SessionJoinRecord', - fields=[ - ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('verify_code', models.CharField(max_length=16, verbose_name='Verify code')), - ('date_joined', models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Date joined')), - ('date_left', models.DateTimeField(db_index=True, null=True, verbose_name='Date left')), - ('remote_addr', models.CharField(blank=True, db_index=True, max_length=128, null=True, verbose_name='Remote addr')), - ('login_from', models.CharField(choices=[('ST', 'SSH Terminal'), ('RT', 'RDP Terminal'), ('WT', 'Web Terminal')], default='WT', max_length=2, verbose_name='Login from')), - ('is_success', models.BooleanField(db_index=True, default=True, verbose_name='Success')), - ('reason', models.CharField(blank=True, default='-', max_length=1024, null=True, verbose_name='Reason')), - ('is_finished', models.BooleanField(db_index=True, default=False, verbose_name='Finished')), - ('joiner', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Joiner')), - ('session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.session', verbose_name='Session')), - ('sharing', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.sessionsharing', verbose_name='Session sharing')), - ], - options={ - 'ordering': ('-date_joined',), - }, - ), - ] diff --git a/apps/terminal/migrations/0041_auto_20211105_1605.py b/apps/terminal/migrations/0041_auto_20211105_1605.py deleted file mode 100644 index ef271abc6..000000000 --- a/apps/terminal/migrations/0041_auto_20211105_1605.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.12 on 2021-11-05 08:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0040_sessionjoinrecord_sessionsharing'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc'), ('telnet', 'telnet'), ('mysql', 'mysql'), ('oracle', 'oracle'), ('mariadb', 'mariadb'), ('sqlserver', 'sqlserver'), ('postgresql', 'postgresql'), ('k8s', 'kubernetes')], db_index=True, default='ssh', max_length=16), - ), - ] diff --git a/apps/terminal/migrations/0042_auto_20211229_1619.py b/apps/terminal/migrations/0042_auto_20211229_1619.py deleted file mode 100644 index bca4c638a..000000000 --- a/apps/terminal/migrations/0042_auto_20211229_1619.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-29 08:19 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0041_auto_20211105_1605'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc'), ('telnet', 'telnet'), ('mysql', 'mysql'), ('redis', 'redis'), ('oracle', 'oracle'), ('mariadb', 'mariadb'), ('sqlserver', 'sqlserver'), ('postgresql', 'postgresql'), ('k8s', 'kubernetes')], db_index=True, default='ssh', max_length=16), - ), - ] diff --git a/apps/terminal/migrations/0043_auto_20220217_2135.py b/apps/terminal/migrations/0043_auto_20220217_2135.py deleted file mode 100644 index 1456d7239..000000000 --- a/apps/terminal/migrations/0043_auto_20220217_2135.py +++ /dev/null @@ -1,64 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-17 13:35 - -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0042_auto_20211229_1619'), - ] - - operations = [ - migrations.AlterModelOptions( - name='command', - options={'ordering': ('-timestamp',), 'verbose_name': 'Command record'}, - ), - migrations.AlterModelOptions( - name='commandstorage', - options={'verbose_name': 'Command storage'}, - ), - migrations.AlterModelOptions( - name='replaystorage', - options={'verbose_name': 'Replay storage'}, - ), - migrations.AlterModelOptions( - name='session', - options={'ordering': ['-date_start'], 'permissions': [('monitor_session', 'Can monitor session'), ('share_session', 'Can share session'), ('terminate_session', 'Can terminate session'), ('validate_sessionactionperm', 'Can validate session action perm')], 'verbose_name': 'Session record'}, - ), - migrations.AlterModelOptions( - name='sessionjoinrecord', - options={'ordering': ('-date_joined',), 'verbose_name': 'Session join record'}, - ), - migrations.AlterModelOptions( - name='sessionsharing', - options={'ordering': ('-date_created',), 'permissions': [('add_supersessionsharing', 'Can add super session sharing')], 'verbose_name': 'Session sharing'}, - ), - migrations.AlterModelOptions( - name='status', - options={'get_latest_by': 'date_created', 'verbose_name': 'Status'}, - ), - migrations.AlterModelOptions( - name='task', - options={'verbose_name': 'Task'}, - ), - migrations.AlterModelOptions( - name='terminal', - options={'ordering': ('is_accepted',), 'permissions': (('view_terminalconfig', 'Can view terminal config'),), 'verbose_name': 'Terminal'}, - ), - migrations.CreateModel( - name='SessionReplay', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.session', verbose_name='Session')), - ], - options={ - 'permissions': [('upload_sessionreplay', 'Can upload session replay'), ('download_sessionreplay', 'Can download session replay')], - }, - ), - ] diff --git a/apps/terminal/migrations/0044_auto_20220223_1539.py b/apps/terminal/migrations/0044_auto_20220223_1539.py deleted file mode 100644 index a1557b008..000000000 --- a/apps/terminal/migrations/0044_auto_20220223_1539.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-23 07:39 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0043_auto_20220217_2135'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='protocol', - field=models.CharField(choices=[('ssh', 'ssh'), ('rdp', 'rdp'), ('vnc', 'vnc'), ('telnet', 'telnet'), ('mysql', 'mysql'), ('oracle', 'oracle'), ('mariadb', 'mariadb'), ('sqlserver', 'sqlserver'), ('postgresql', 'postgresql'), ('redis', 'redis'), ('mongodb', 'MongoDB'), ('k8s', 'kubernetes')], db_index=True, default='ssh', max_length=16), - ), - ] diff --git a/apps/terminal/migrations/0045_auto_20220228_1144.py b/apps/terminal/migrations/0045_auto_20220228_1144.py deleted file mode 100644 index 000dcb53b..000000000 --- a/apps/terminal/migrations/0045_auto_20220228_1144.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-28 03:44 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0044_auto_20220223_1539'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='login_from', - field=models.CharField(choices=[('ST', 'SSH Terminal'), ('RT', 'RDP Terminal'), ('WT', 'Web Terminal'), ('DT', 'DB Terminal')], default='ST', max_length=2, verbose_name='Login from'), - ), - migrations.AlterField( - model_name='sessionjoinrecord', - name='login_from', - field=models.CharField(choices=[('ST', 'SSH Terminal'), ('RT', 'RDP Terminal'), ('WT', 'Web Terminal'), ('DT', 'DB Terminal')], default='WT', max_length=2, verbose_name='Login from'), - ), - migrations.AlterField( - model_name='terminal', - name='type', - field=models.CharField(choices=[('koko', 'KoKo'), ('guacamole', 'Guacamole'), ('omnidb', 'OmniDB'), ('xrdp', 'Xrdp'), ('lion', 'Lion'), ('core', 'Core'), ('celery', 'Celery'), ('magnus', 'Magnus')], default='koko', max_length=64, verbose_name='type'), - ), - ] diff --git a/apps/terminal/migrations/0046_auto_20220228_1744.py b/apps/terminal/migrations/0046_auto_20220228_1744.py deleted file mode 100644 index be651022f..000000000 --- a/apps/terminal/migrations/0046_auto_20220228_1744.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-28 09:44 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0045_auto_20220228_1144'), - ] - - operations = [ - migrations.AlterField( - model_name='replaystorage', - name='type', - field=models.CharField(choices=[('null', 'Null'), ('server', 'Server'), ('s3', 'S3'), ('ceph', 'Ceph'), ('swift', 'Swift'), ('oss', 'OSS'), ('azure', 'Azure'), ('obs', 'OBS'), ('cos', 'COS')], default='server', max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/terminal/migrations/0047_auto_20220302_1951.py b/apps/terminal/migrations/0047_auto_20220302_1951.py deleted file mode 100644 index a67b260b8..000000000 --- a/apps/terminal/migrations/0047_auto_20220302_1951.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.14 on 2022-03-02 11:51 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0046_auto_20220228_1744'), - ] - - operations = [ - migrations.AlterModelOptions( - name='sessionreplay', - options={'permissions': [('upload_sessionreplay', 'Can upload session replay'), ('download_sessionreplay', 'Can download session replay')], 'verbose_name': 'Session replay'}, - ), - ] diff --git a/apps/terminal/migrations/0048_endpoint_endpointrule.py b/apps/terminal/migrations/0048_endpoint_endpointrule.py deleted file mode 100644 index 1c1ef2d8c..000000000 --- a/apps/terminal/migrations/0048_endpoint_endpointrule.py +++ /dev/null @@ -1,119 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-12 07:39 - -import common.db.fields -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion -import uuid -from django.conf import settings - - -def migrate_endpoints(apps, schema_editor): - Endpoint = apps.get_model("terminal", "Endpoint") - # migrate default - default_data = { - 'id': '00000000-0000-0000-0000-000000000001', - 'name': 'Default', - 'host': '', - 'https_port': 0, - 'http_port': 0, - 'created_by': 'System' - } - Endpoint.objects.create(**default_data) - - if not settings.TERMINAL_RAZOR_ENABLED: - return - # migrate xrdp - xrdp_addr = settings.TERMINAL_RDP_ADDR - if ':' in xrdp_addr: - host, rdp_port = xrdp_addr.strip().split(':') - else: - host, rdp_port = xrdp_addr, 3389 - host = host.strip() - if host in ['localhost', '127.0.0.1']: - host = '' - if not host: - return - if isinstance(rdp_port, str) and rdp_port.isdigit(): - rdp_port = int(rdp_port) - elif isinstance(rdp_port, int) and (0 <= rdp_port <= 65535): - rdp_port = rdp_port - else: - rdp_port = 3389 - xrdp_data = { - 'name': 'Razor', - 'host': host, - 'https_port': 0, - 'http_port': 0, - 'ssh_port': 0, - 'rdp_port': rdp_port, - 'mysql_port': 0, - 'mariadb_port': 0, - 'postgresql_port': 0, - 'created_by': 'System' - } - xrdp_endpoint = Endpoint.objects.create(**xrdp_data) - - EndpointRule = apps.get_model("terminal", "EndpointRule") - xrdp_rule_data = { - 'name': 'Razor', - 'ip_group': ['*'], - 'priority': 20, - 'endpoint': xrdp_endpoint, - 'created_by': 'System' - } - EndpointRule.objects.create(**xrdp_rule_data) - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0047_auto_20220302_1951'), - ] - - operations = [ - migrations.CreateModel( - name='Endpoint', - fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('host', models.CharField(max_length=256, verbose_name='Host', blank=True)), - ('https_port', common.db.fields.PortField(default=443, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='HTTPS port')), - ('http_port', common.db.fields.PortField(default=80, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='HTTP port')), - ('ssh_port', common.db.fields.PortField(default=2222, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='SSH port')), - ('rdp_port', common.db.fields.PortField(default=3389, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='RDP port')), - ('mysql_port', common.db.fields.PortField(default=33061, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='MySQL port')), - ('mariadb_port', common.db.fields.PortField(default=33062, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='MariaDB port')), - ('postgresql_port', common.db.fields.PortField(default=54320, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='PostgreSQL port')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ], - options={ - 'verbose_name': 'Endpoint', - 'ordering': ('name',), - }, - ), - migrations.CreateModel( - name='EndpointRule', - fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, 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)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('ip_group', models.JSONField(default=list, verbose_name='IP group')), - ('priority', models.IntegerField(help_text='1-100, the lower the value will be match first', unique=True, validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)], verbose_name='Priority')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('endpoint', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rules', to='terminal.endpoint', verbose_name='Endpoint')), - ], - options={ - 'verbose_name': 'Endpoint rule', - 'ordering': ('priority', 'name'), - }, - ), - migrations.RunPython(migrate_endpoints), - ] diff --git a/apps/terminal/migrations/0049_endpoint_redis_port.py b/apps/terminal/migrations/0049_endpoint_redis_port.py deleted file mode 100644 index aa4d722bc..000000000 --- a/apps/terminal/migrations/0049_endpoint_redis_port.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 3.1.14 on 2022-05-12 06:35 - -import common.db.fields -import django.core.validators -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0048_endpoint_endpointrule'), - ] - - operations = [ - migrations.AddField( - model_name='endpoint', - name='redis_port', - field=common.db.fields.PortField(default=63790, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='Redis port'), - ), - ] diff --git a/apps/terminal/migrations/0050_auto_20220606_1745.py b/apps/terminal/migrations/0050_auto_20220606_1745.py deleted file mode 100644 index 05e15f866..000000000 --- a/apps/terminal/migrations/0050_auto_20220606_1745.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 3.1.14 on 2022-06-06 09:45 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('terminal', '0049_endpoint_redis_port'), - ] - - operations = [ - migrations.AlterField( - model_name='terminal', - name='type', - field=models.CharField( - choices=[('koko', 'KoKo'), ('guacamole', 'Guacamole'), ('omnidb', 'OmniDB'), ('xrdp', 'Xrdp'), - ('lion', 'Lion'), ('core', 'Core'), ('celery', 'Celery'), ('magnus', 'Magnus'), - ('razor', 'Razor'), ('tinker', 'Tinker'), ('video_worker', 'Video Worker'), ('chen', 'Chen'), - ('kael', 'Kael')], default='koko', max_length=64, verbose_name='type'), - ), - ] diff --git a/apps/terminal/migrations/0051_sessionsharing_users.py b/apps/terminal/migrations/0051_sessionsharing_users.py deleted file mode 100644 index f32224dea..000000000 --- a/apps/terminal/migrations/0051_sessionsharing_users.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.14 on 2022-06-30 03:38 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0050_auto_20220606_1745'), - ] - - operations = [ - migrations.AddField( - model_name='sessionsharing', - name='users', - field=models.TextField(blank=True, verbose_name='User'), - ), - ] diff --git a/apps/terminal/migrations/0052_auto_20220713_1417.py b/apps/terminal/migrations/0052_auto_20220713_1417.py deleted file mode 100644 index 52c5d907f..000000000 --- a/apps/terminal/migrations/0052_auto_20220713_1417.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.1.14 on 2022-04-07 09:26 - -import common.db.fields -import django.core.validators -from django.db import migrations - - -class Migration(migrations.Migration): - dependencies = [ - ('terminal', '0051_sessionsharing_users'), - ] - - operations = [ - migrations.AddField( - model_name='endpoint', - name='oracle_11g_port', - field=common.db.fields.PortField(default=15211, validators=[ - django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(65535)], verbose_name='Oracle 11g port'), - ), - migrations.AddField( - model_name='endpoint', - name='oracle_12c_port', - field=common.db.fields.PortField(default=15212, validators=[ - django.core.validators.MinValueValidator(0), - django.core.validators.MaxValueValidator(65535)], verbose_name='Oracle 12c port'), - ), - ] diff --git a/apps/terminal/migrations/0053_auto_20221009_1755.py b/apps/terminal/migrations/0053_auto_20221009_1755.py deleted file mode 100644 index 0a6e30993..000000000 --- a/apps/terminal/migrations/0053_auto_20221009_1755.py +++ /dev/null @@ -1,37 +0,0 @@ -# Generated by Django 3.2.15 on 2022-10-09 09:55 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0052_auto_20220713_1417'), - ] - - operations = [ - migrations.RemoveField( - model_name='endpoint', - name='mariadb_port', - ), - migrations.RemoveField( - model_name='endpoint', - name='mysql_port', - ), - migrations.RemoveField( - model_name='endpoint', - name='oracle_11g_port', - ), - migrations.RemoveField( - model_name='endpoint', - name='oracle_12c_port', - ), - migrations.RemoveField( - model_name='endpoint', - name='postgresql_port', - ), - migrations.RemoveField( - model_name='endpoint', - name='redis_port', - ), - ] diff --git a/apps/terminal/migrations/0054_auto_20221027_1125.py b/apps/terminal/migrations/0054_auto_20221027_1125.py deleted file mode 100644 index 4b101aea0..000000000 --- a/apps/terminal/migrations/0054_auto_20221027_1125.py +++ /dev/null @@ -1,45 +0,0 @@ -# Generated by Django 3.2.14 on 2022-10-27 03:25 - -import uuid - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0101_auto_20220811_1511'), - ('terminal', '0053_auto_20221009_1755'), - ] - - operations = [ - migrations.AlterField( - model_name='session', - name='protocol', - field=models.CharField(db_index=True, default='ssh', max_length=16), - ), - migrations.RenameField( - model_name='session', - old_name='system_user', - new_name='account', - ), - migrations.RemoveField( - model_name='session', - name='system_user_id', - ), - migrations.AlterField( - model_name='session', - name='account', - field=models.CharField(db_index=True, max_length=128, verbose_name='Account'), - ), - migrations.AddField( - model_name='session', - name='comment', - field=models.TextField(blank=True, null=True, verbose_name='Comment'), - ), - migrations.AddField( - model_name='session', - name='type', - field=models.CharField(db_index=True, default='normal', max_length=16), - ), - ] diff --git a/apps/terminal/migrations/0055_auto_20221228_1804.py b/apps/terminal/migrations/0055_auto_20221228_1804.py deleted file mode 100644 index 126cbdbbf..000000000 --- a/apps/terminal/migrations/0055_auto_20221228_1804.py +++ /dev/null @@ -1,176 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-28 10:04 - -from django.db import migrations, models -import django.db.models.deletion -import uuid - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0105_auto_20221220_1956'), - ('terminal', '0054_auto_20221027_1125'), - ] - - operations = [ - migrations.AlterModelOptions( - name='terminal', - options={'permissions': (('view_terminalconfig', 'Can view terminal config'),), 'verbose_name': 'Terminal'}, - ), - migrations.RenameField( - model_name='command', - old_name='system_user', - new_name='account', - ), - migrations.AlterField( - model_name='command', - name='account', - field=models.CharField(db_index=True, max_length=64, verbose_name='Account'), - ), - migrations.RemoveField( - model_name='terminal', - name='http_port', - ), - migrations.RemoveField( - model_name='terminal', - name='is_accepted', - ), - migrations.RemoveField( - model_name='terminal', - name='ssh_port', - ), - migrations.AddField( - model_name='commandstorage', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='replaystorage', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='sessionjoinrecord', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='sessionjoinrecord', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='sessionreplay', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='sessionreplay', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='sessionsharing', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='sessionsharing', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='task', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='task', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AddField( - model_name='task', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='task', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='terminal', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AddField( - model_name='terminal', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='terminal', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='commandstorage', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='endpoint', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='endpoint', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='endpointrule', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='endpointrule', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='replaystorage', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='sessionjoinrecord', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='sessionreplay', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='sessionsharing', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='task', - name='date_created', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created'), - ), - migrations.AlterField( - model_name='terminal', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='terminal', - name='date_created', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created'), - ), - ] diff --git a/apps/terminal/migrations/0056_auto_20221228_1808.py b/apps/terminal/migrations/0056_auto_20221228_1808.py deleted file mode 100644 index c4b5b8a14..000000000 --- a/apps/terminal/migrations/0056_auto_20221228_1808.py +++ /dev/null @@ -1,125 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-28 10:08 - -import uuid - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('assets', '0105_auto_20221220_1956'), - ('terminal', '0055_auto_20221228_1804'), - ] - - operations = [ - migrations.CreateModel( - name='Applet', - 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)), - ('name', models.SlugField(max_length=128, unique=True, verbose_name='Name')), - ('display_name', models.CharField(max_length=128, verbose_name='Display name')), - ('version', models.CharField(max_length=16, verbose_name='Version')), - ('author', models.CharField(max_length=128, verbose_name='Author')), - ('type', - models.CharField(choices=[('general', 'General'), ('web', 'Web')], default='general', max_length=16, - verbose_name='Type')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('builtin', models.BooleanField(default=False, verbose_name='Builtin')), - ('protocols', models.JSONField(default=list, verbose_name='Protocol')), - ('tags', models.JSONField(default=list, verbose_name='Tags')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ], - options={ - 'verbose_name': 'Applet', - }, - ), - migrations.CreateModel( - name='AppletHost', - fields=[ - ('host_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='assets.host')), - ('deploy_options', models.JSONField(default=dict, verbose_name='Deploy options')), - ('inited', models.BooleanField(default=False, verbose_name='Inited')), - ('date_inited', models.DateTimeField(blank=True, null=True, verbose_name='Date inited')), - ('date_synced', models.DateTimeField(blank=True, null=True, verbose_name='Date synced')), - ], - options={ - 'verbose_name': 'Applet host', - }, - bases=('assets.host',), - ), - migrations.CreateModel( - name='AppletPublication', - 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)), - ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('applet', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='publications', - to='terminal.applet', verbose_name='Applet')), - ('host', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='publications', - to='terminal.applethost', verbose_name='Host')), - ], - options={ - 'unique_together': {('applet', 'host')}, - }, - ), - migrations.CreateModel( - name='AppletHostDeployment', - 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)), - ('initial', models.BooleanField(default=False, verbose_name='Initial')), - ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), - ('date_start', models.DateTimeField(db_index=True, null=True, verbose_name='Date start')), - ('date_finished', models.DateTimeField(null=True, verbose_name='Date finished')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('task', models.UUIDField(null=True, verbose_name='Task')), - ('host', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='terminal.applethost', - verbose_name='Hosting')), - ], - options={ - 'ordering': ('-date_start',), - }, - ), - migrations.AddField( - model_name='applethost', - name='applets', - field=models.ManyToManyField(through='terminal.AppletPublication', to='terminal.Applet', - verbose_name='Applet'), - ), - migrations.AddField( - model_name='applethost', - name='terminal', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, - related_name='applet_host', to='terminal.terminal', verbose_name='Terminal'), - ), - migrations.AddField( - model_name='applet', - name='hosts', - field=models.ManyToManyField(through='terminal.AppletPublication', to='terminal.AppletHost', - verbose_name='Hosts'), - ), - migrations.AlterField( - model_name='appletpublication', - name='applet', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publications', to='terminal.applet', verbose_name='Applet'), - ), - migrations.AlterField( - model_name='appletpublication', - name='host', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publications', to='terminal.applethost', verbose_name='Host'), - ), - ] diff --git a/apps/terminal/migrations/0057_auto_20230109_1447.py b/apps/terminal/migrations/0057_auto_20230109_1447.py deleted file mode 100644 index 6bb719828..000000000 --- a/apps/terminal/migrations/0057_auto_20230109_1447.py +++ /dev/null @@ -1,40 +0,0 @@ -# Generated by Django 3.2.14 on 2023-01-09 06:47 - -import common.db.fields -import django.core.validators -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0056_auto_20221228_1808'), - ] - - operations = [ - migrations.AddField( - model_name='endpoint', - name='mariadb_port', - field=common.db.fields.PortField(default=33062, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='MariaDB port'), - ), - migrations.AddField( - model_name='endpoint', - name='mysql_port', - field=common.db.fields.PortField(default=33061, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='MySQL port'), - ), - migrations.AddField( - model_name='endpoint', - name='oracle_port_range', - field=common.db.fields.PortRangeField(default='1-65535', max_length=16, verbose_name='Oracle port range'), - ), - migrations.AddField( - model_name='endpoint', - name='postgresql_port', - field=common.db.fields.PortField(default=54320, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='PostgreSQL port'), - ), - migrations.AddField( - model_name='endpoint', - name='redis_port', - field=common.db.fields.PortField(default=63790, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='Redis port'), - ), - ] diff --git a/apps/terminal/migrations/0058_auto_20230110_1445.py b/apps/terminal/migrations/0058_auto_20230110_1445.py deleted file mode 100644 index 1c6d87fbf..000000000 --- a/apps/terminal/migrations/0058_auto_20230110_1445.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 3.2.16 on 2023-01-10 06:45 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0057_auto_20230109_1447'), - ] - - operations = [ - migrations.AlterModelOptions( - name='applethost', - options={'verbose_name': 'Hosting'}, - ), - migrations.RemoveField( - model_name='endpoint', - name='oracle_port_range', - ), - migrations.AlterField( - model_name='appletpublication', - name='host', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publications', to='terminal.applethost', verbose_name='Hosting'), - ), - ] diff --git a/apps/terminal/migrations/0059_session_account_id.py b/apps/terminal/migrations/0059_session_account_id.py deleted file mode 100644 index 52168b775..000000000 --- a/apps/terminal/migrations/0059_session_account_id.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.2.14 on 2023-02-14 10:54 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0058_auto_20230110_1445'), - ] - - operations = [ - migrations.AddField( - model_name='session', - name='account_id', - field=models.CharField(db_index=True, default='', max_length=128, verbose_name='Account id'), - preserve_default=False, - ), - ] diff --git a/apps/terminal/migrations/0060_sessionsharing_action_permission.py b/apps/terminal/migrations/0060_sessionsharing_action_permission.py deleted file mode 100644 index 1e0bcab94..000000000 --- a/apps/terminal/migrations/0060_sessionsharing_action_permission.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.17 on 2023-04-03 06:28 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0059_session_account_id'), - ] - - operations = [ - migrations.AddField( - model_name='sessionsharing', - name='action_permission', - field=models.CharField(default='writable', max_length=16, verbose_name='Action permission'), - ), - ] diff --git a/apps/terminal/migrations/0061_applet_can_concurrent.py b/apps/terminal/migrations/0061_applet_can_concurrent.py deleted file mode 100644 index 5041e5425..000000000 --- a/apps/terminal/migrations/0061_applet_can_concurrent.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.17 on 2023-05-09 11:02 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0060_sessionsharing_action_permission'), - ] - - operations = [ - migrations.AddField( - model_name='applet', - name='can_concurrent', - field=models.BooleanField(default=False, verbose_name='Can concurrent'), - ), - ] diff --git a/apps/terminal/migrations/0062_applet_edition.py b/apps/terminal/migrations/0062_applet_edition.py deleted file mode 100644 index 8ca93ce2f..000000000 --- a/apps/terminal/migrations/0062_applet_edition.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.17 on 2023-06-09 02:50 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('terminal', '0061_applet_can_concurrent'), - ] - - operations = [ - migrations.AddField( - model_name='applet', - name='edition', - field=models.CharField(choices=[('community', 'Community edition'), ('enterprise', 'Enterprise')], - default='community', max_length=128, verbose_name='Edition'), - ), - ] diff --git a/apps/terminal/migrations/0063_auto_20230621_1133.py b/apps/terminal/migrations/0063_auto_20230621_1133.py deleted file mode 100644 index 85553e8f3..000000000 --- a/apps/terminal/migrations/0063_auto_20230621_1133.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.2.19 on 2023-06-21 10:25 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0062_applet_edition'), - ] - - operations = [ - migrations.AlterModelOptions( - name='endpointrule', - options={'ordering': ('priority', 'is_active', 'name'), 'verbose_name': 'Endpoint rule'}, - ), - migrations.AddField( - model_name='endpointrule', - name='is_active', - field=models.BooleanField(default=True, verbose_name='Is active'), - ), - ] diff --git a/apps/terminal/migrations/0064_auto_20230728_1001.py b/apps/terminal/migrations/0064_auto_20230728_1001.py deleted file mode 100644 index 93af187c4..000000000 --- a/apps/terminal/migrations/0064_auto_20230728_1001.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 4.1.10 on 2023-07-28 02:01 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0063_auto_20230621_1133'), - ] - - operations = [ - migrations.AddField( - model_name='applethost', - name='accounts_create_amount', - field=models.IntegerField(default=100, verbose_name='Accounts create amount'), - ), - migrations.AddField( - model_name='applethost', - name='auto_create_accounts', - field=models.BooleanField(default=True, verbose_name='Auto create accounts'), - ), - migrations.AddField( - model_name='sessionsharing', - name='origin', - field=models.URLField(blank=True, null=True, verbose_name='Origin'), - ), - migrations.AddField( - model_name='session', - name='cmd_amount', - field=models.IntegerField(default=-1, verbose_name='Command amount'), - ), - migrations.AlterField( - model_name='task', - name='name', - field=models.CharField(choices=[('kill_session', 'Kill session'), ('lock_session', 'Lock session'), ('unlock_session', 'Unlock session')], max_length=128, verbose_name='Name'), - ), - ] diff --git a/apps/terminal/migrations/0065_session_error_reason.py b/apps/terminal/migrations/0065_session_error_reason.py deleted file mode 100644 index 1a3bf8f67..000000000 --- a/apps/terminal/migrations/0065_session_error_reason.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-10 06:24 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0064_auto_20230728_1001'), - ] - - operations = [ - migrations.AddField( - model_name='session', - name='error_reason', - field=models.CharField(blank=True, max_length=128, verbose_name='Error reason'), - ), - ] diff --git a/apps/terminal/migrations/0066_applethost_using_same_account.py b/apps/terminal/migrations/0066_applethost_using_same_account.py deleted file mode 100644 index 467eaab6d..000000000 --- a/apps/terminal/migrations/0066_applethost_using_same_account.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-30 03:08 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0065_session_error_reason'), - ] - - operations = [ - migrations.AddField( - model_name='applethost', - name='using_same_account', - field=models.BooleanField(default=False, verbose_name='Using same account'), - ), - ] diff --git a/apps/terminal/migrations/0067_alter_replaystorage_type.py b/apps/terminal/migrations/0067_alter_replaystorage_type.py deleted file mode 100644 index a35343407..000000000 --- a/apps/terminal/migrations/0067_alter_replaystorage_type.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-02 10:07 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0066_applethost_using_same_account'), - ] - - operations = [ - migrations.AlterField( - model_name='replaystorage', - name='type', - field=models.CharField(choices=[('null', 'Null'), ('server', 'Server'), ('s3', 'S3'), ('ceph', 'Ceph'), ('swift', 'Swift'), ('oss', 'OSS'), ('azure', 'Azure'), ('obs', 'OBS'), ('cos', 'COS'), ('sftp', 'SFTP')], default='server', max_length=16, verbose_name='Type'), - ), - ] diff --git a/apps/terminal/migrations/0068_virtualapp.py b/apps/terminal/migrations/0068_virtualapp.py deleted file mode 100644 index 1ac230620..000000000 --- a/apps/terminal/migrations/0068_virtualapp.py +++ /dev/null @@ -1,94 +0,0 @@ -# Generated by Django 4.1.10 on 2023-12-05 07:02 - -import uuid - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0067_alter_replaystorage_type'), - ] - - operations = [ - migrations.CreateModel( - name='AppProvider', - 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')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), - ('hostname', models.CharField(max_length=128, verbose_name='Hostname')), - ], - options={ - 'ordering': ('-date_created',), - }, - ), - migrations.CreateModel( - name='VirtualApp', - 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)), - ('name', models.SlugField(max_length=128, unique=True, verbose_name='Name')), - ('display_name', models.CharField(max_length=128, verbose_name='Display name')), - ('version', models.CharField(max_length=16, verbose_name='Version')), - ('author', models.CharField(max_length=128, verbose_name='Author')), - ('is_active', models.BooleanField(default=True, verbose_name='Is active')), - ('protocols', models.JSONField(default=list, verbose_name='Protocol')), - ('image_name', models.CharField(max_length=128, verbose_name='Image name')), - ('image_protocol', models.CharField(default='vnc', max_length=16, verbose_name='Image protocol')), - ('image_port', models.IntegerField(default=5900, verbose_name='Image port')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('tags', models.JSONField(default=list, verbose_name='Tags')), - ], - options={ - 'verbose_name': 'Virtual app', - }, - ), - migrations.AlterField( - model_name='terminal', - name='type', - field=models.CharField(choices=[('koko', 'KoKo'), ('guacamole', 'Guacamole'), ('omnidb', 'OmniDB'), ('xrdp', 'Xrdp'), ('lion', 'Lion'), ('core', 'Core'), ('celery', 'Celery'), ('magnus', 'Magnus'), ('razor', 'Razor'), ('tinker', 'Tinker'), ('video_worker', 'Video Worker'), ('chen', 'Chen'), ('kael', 'Kael'), ('panda', 'Panda')], default='koko', max_length=64, verbose_name='type'), - ), - migrations.CreateModel( - name='VirtualAppPublication', - 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')), - ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('status', models.CharField(default='pending', max_length=16, verbose_name='Status')), - ('app', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publications', to='terminal.virtualapp', verbose_name='Virtual app')), - ('provider', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='publications', to='terminal.appprovider', verbose_name='App Provider')), - ], - options={ - 'verbose_name': 'Virtual app publication', - 'unique_together': {('provider', 'app')}, - }, - ), - migrations.AddField( - model_name='virtualapp', - name='providers', - field=models.ManyToManyField(through='terminal.VirtualAppPublication', to='terminal.appprovider', verbose_name='Providers'), - ), - migrations.AddField( - model_name='appprovider', - name='apps', - field=models.ManyToManyField(through='terminal.VirtualAppPublication', to='terminal.virtualapp', verbose_name='Virtual app'), - ), - migrations.AddField( - model_name='appprovider', - name='terminal', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='app_provider', to='terminal.terminal', verbose_name='Terminal'), - ), - ] diff --git a/apps/terminal/migrations/0069_endpoint_sqlserver_port_alter_appprovider_apps_and_more.py b/apps/terminal/migrations/0069_endpoint_sqlserver_port_alter_appprovider_apps_and_more.py deleted file mode 100644 index f68cca188..000000000 --- a/apps/terminal/migrations/0069_endpoint_sqlserver_port_alter_appprovider_apps_and_more.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.1.10 on 2023-12-08 09:41 - -import common.db.fields -import django.core.validators -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0068_virtualapp'), - ] - - operations = [ - migrations.AddField( - model_name='endpoint', - name='sqlserver_port', - field=common.db.fields.PortField(default=14330, validators=[django.core.validators.MinValueValidator(0), django.core.validators.MaxValueValidator(65535)], verbose_name='SQLServer port'), - ), - ] diff --git a/apps/tickets/migrations/0001_initial.py b/apps/tickets/migrations/0001_initial.py index 83be9a78d..9db938f25 100644 --- a/apps/tickets/migrations/0001_initial.py +++ b/apps/tickets/migrations/0001_initial.py @@ -1,9 +1,9 @@ -# Generated by Django 2.2.5 on 2019-11-15 06:57 +# Generated by Django 4.1.13 on 2024-05-09 03:16 -import common.db.fields -from django.conf import settings +import common.db.encoder from django.db import migrations, models import django.db.models.deletion +import tickets.models.ticket.general import uuid @@ -12,48 +12,182 @@ class Migration(migrations.Migration): initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('terminal', '0001_initial'), ] operations = [ migrations.CreateModel( - name='Ticket', + name='ApprovalRule', fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), + ('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')), - ('user_display', models.CharField(max_length=128, verbose_name='User display name')), - ('title', models.CharField(max_length=256, verbose_name='Title')), - ('body', models.TextField(verbose_name='Body')), - ('meta', common.db.fields.JsonDictTextField(default='{}', verbose_name='Meta')), - ('assignee_display', models.CharField(blank=True, max_length=128, null=True, verbose_name='Assignee display name')), - ('assignees_display', models.CharField(blank=True, max_length=128, verbose_name='Assignees display name')), - ('type', models.CharField(choices=[('general', 'General'), ('login_confirm', 'Login confirm')], default='general', max_length=16, verbose_name='Type')), - ('status', models.CharField(choices=[('open', 'Open'), ('closed', 'Closed')], default='open', max_length=16)), - ('action', models.CharField(blank=True, choices=[('approve', 'Approve'), ('reject', 'Reject')], default='', max_length=16)), - ('assignee', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ticket_handled', to=settings.AUTH_USER_MODEL, verbose_name='Assignee')), - ('assignees', models.ManyToManyField(related_name='ticket_assigned', to=settings.AUTH_USER_MODEL, verbose_name='Assignees')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='ticket_requested', to=settings.AUTH_USER_MODEL, verbose_name='User')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('level', models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1, verbose_name='Approve level')), + ('strategy', models.CharField(choices=[('org_admin', 'Org admin'), ('custom_user', 'Custom user'), ('super_admin', 'Super admin'), ('super_org_admin', 'Super admin and org admin')], default='super_admin', max_length=64, verbose_name='Approve strategy')), ], options={ - 'ordering': ('-date_created',), + 'verbose_name': 'Ticket flow approval rule', }, ), migrations.CreateModel( name='Comment', fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), + ('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')), - ('user_display', models.CharField(max_length=128, verbose_name='User display name')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('user_display', models.CharField(max_length=256, verbose_name='User display name')), ('body', models.TextField(verbose_name='Body')), - ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='tickets.Ticket')), - ('user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='comments', to=settings.AUTH_USER_MODEL, verbose_name='User')), + ('type', models.CharField(choices=[('state', 'State'), ('common', 'common')], default='common', max_length=16, verbose_name='Type')), + ('state', models.CharField(max_length=16, null=True)), ], options={ + 'verbose_name': 'Comment', 'ordering': ('date_created',), }, ), + migrations.CreateModel( + name='Ticket', + 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)), + ('title', models.CharField(max_length=256, verbose_name='Title')), + ('type', models.CharField(choices=[('general', 'General'), ('apply_asset', 'Apply for asset'), ('login_confirm', 'Login confirm'), ('command_confirm', 'Command confirm'), ('login_asset_confirm', 'Login asset confirm')], default='general', max_length=64, verbose_name='Type')), + ('state', models.CharField(choices=[('pending', 'Open'), ('closed', 'Cancel'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='pending', max_length=16, verbose_name='State')), + ('status', models.CharField(choices=[('open', 'Open'), ('closed', 'Finished')], default='open', max_length=16, verbose_name='Status')), + ('approval_step', models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1, verbose_name='Approval step')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('rel_snapshot', models.JSONField(default=dict, verbose_name='Relation snapshot')), + ('serial_num', models.CharField(max_length=128, null=True, verbose_name='Serial number')), + ('meta', models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, verbose_name='Meta')), + ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), + ], + options={ + 'verbose_name': 'Ticket', + 'ordering': ('-date_created',), + }, + bases=(tickets.models.ticket.general.StatusMixin, models.Model), + ), + migrations.CreateModel( + name='TicketAssignee', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('state', models.CharField(choices=[('pending', 'Open'), ('closed', 'Cancel'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='pending', max_length=64)), + ], + options={ + 'verbose_name': 'Ticket assignee', + }, + ), + migrations.CreateModel( + name='ApplyAssetTicket', + fields=[ + ('ticket_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tickets.ticket')), + ('apply_permission_name', models.CharField(max_length=128, verbose_name='Permission name')), + ('apply_accounts', models.JSONField(default=list, verbose_name='Apply accounts')), + ('apply_actions', models.IntegerField(default=1, verbose_name='Actions')), + ('apply_date_start', models.DateTimeField(null=True, verbose_name='Date start')), + ('apply_date_expired', models.DateTimeField(null=True, verbose_name='Date expired')), + ], + options={ + 'verbose_name': 'Apply Asset Ticket', + }, + bases=('tickets.ticket',), + ), + migrations.CreateModel( + name='ApplyCommandTicket', + fields=[ + ('ticket_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tickets.ticket')), + ('apply_run_asset', models.CharField(max_length=128, verbose_name='Run asset')), + ('apply_run_command', models.CharField(max_length=4096, verbose_name='Run command')), + ('apply_run_account', models.CharField(default='', max_length=128, verbose_name='Account')), + ], + options={ + 'verbose_name': 'Apply Command Ticket', + }, + bases=('tickets.ticket',), + ), + migrations.CreateModel( + name='ApplyLoginAssetTicket', + fields=[ + ('ticket_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tickets.ticket')), + ('apply_login_account', models.CharField(default='', max_length=128, verbose_name='Login account')), + ], + options={ + 'verbose_name': 'Apply Login Asset Ticket', + }, + bases=('tickets.ticket',), + ), + migrations.CreateModel( + name='ApplyLoginTicket', + fields=[ + ('ticket_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='tickets.ticket')), + ('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_datetime', models.DateTimeField(null=True, verbose_name='Login Date')), + ], + options={ + 'verbose_name': 'Apply Login Ticket', + }, + bases=('tickets.ticket',), + ), + migrations.CreateModel( + name='TicketStep', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('level', models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1, verbose_name='Approve level')), + ('state', models.CharField(choices=[('pending', 'Pending'), ('closed', 'Closed'), ('approved', 'Approved'), ('rejected', 'Rejected')], default='pending', max_length=64, verbose_name='State')), + ('status', models.CharField(choices=[('active', 'Active'), ('closed', 'Closed'), ('pending', 'Pending')], default='pending', max_length=16)), + ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_steps', to='tickets.ticket', verbose_name='Ticket')), + ], + options={ + 'verbose_name': 'Ticket step', + }, + ), + migrations.CreateModel( + name='TicketSession', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('session', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_relation', to='terminal.session')), + ('ticket', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, related_name='session_relation', to='tickets.ticket')), + ], + options={ + 'verbose_name': 'Ticket session relation', + }, + ), + migrations.CreateModel( + name='TicketFlow', + 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')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('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')), + ('type', models.CharField(choices=[('general', 'General'), ('apply_asset', 'Apply for asset'), ('login_confirm', 'Login confirm'), ('command_confirm', 'Command confirm'), ('login_asset_confirm', 'Login asset confirm')], default='general', max_length=64, verbose_name='Type')), + ('approval_level', models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1, verbose_name='Approve level')), + ('rules', models.ManyToManyField(related_name='ticket_flows', to='tickets.approvalrule')), + ], + options={ + 'verbose_name': 'Ticket flow', + }, + ), ] diff --git a/apps/tickets/migrations/0002_auto_20200728_1146.py b/apps/tickets/migrations/0002_auto_20200728_1146.py index 303395144..892ba2127 100644 --- a/apps/tickets/migrations/0002_auto_20200728_1146.py +++ b/apps/tickets/migrations/0002_auto_20200728_1146.py @@ -1,30 +1,107 @@ -# Generated by Django 2.2.10 on 2020-07-28 03:46 +# Generated by Django 4.1.13 on 2024-05-09 03:16 +from django.conf import settings from django.db import migrations, models -import django.db.models.manager +import django.db.models.deletion class Migration(migrations.Migration): + initial = True + dependencies = [ + ('acls', '0002_auto_20210926_1047'), + ('terminal', '0002_auto_20171228_0025'), ('tickets', '0001_initial'), + ('assets', '0002_auto_20180105_1807'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ - migrations.AlterModelManagers( - name='ticket', - managers=[ - ('origin_objects', django.db.models.manager.Manager()), - ], + migrations.AddField( + model_name='ticketassignee', + name='assignee', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_assignees', to=settings.AUTH_USER_MODEL, verbose_name='Assignee'), + ), + migrations.AddField( + model_name='ticketassignee', + name='step', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_assignees', to='tickets.ticketstep'), ), migrations.AddField( model_name='ticket', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), + name='applicant', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='applied_tickets', to=settings.AUTH_USER_MODEL, verbose_name='Applicant'), ), - migrations.AlterField( + migrations.AddField( model_name='ticket', - name='type', - field=models.CharField(choices=[('general', 'General'), ('login_confirm', 'Login confirm'), ('request_asset', 'Request asset permission')], default='general', max_length=16, verbose_name='Type'), + name='flow', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets', to='tickets.ticketflow', verbose_name='TicketFlow'), + ), + migrations.AddField( + model_name='comment', + name='ticket', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='tickets.ticket'), + ), + migrations.AddField( + model_name='comment', + name='user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='comments', to=settings.AUTH_USER_MODEL, verbose_name='User'), + ), + migrations.AddField( + model_name='approvalrule', + name='assignees', + field=models.ManyToManyField(related_name='assigned_ticket_flow_approval_rule', to=settings.AUTH_USER_MODEL, verbose_name='Assignees'), + ), + migrations.CreateModel( + name='SuperTicket', + fields=[ + ], + options={ + 'verbose_name': 'Super ticket', + 'proxy': True, + 'indexes': [], + 'constraints': [], + }, + bases=('tickets.ticket',), + ), + migrations.AlterUniqueTogether( + name='ticket', + unique_together={('serial_num',)}, + ), + migrations.AddField( + model_name='applyloginassetticket', + name='apply_login_asset', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.asset', verbose_name='Login asset'), + ), + migrations.AddField( + model_name='applyloginassetticket', + name='apply_login_user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Login user'), + ), + migrations.AddField( + model_name='applycommandticket', + name='apply_from_cmd_filter_acl', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='acls.commandfilteracl', verbose_name='Command filter acl'), + ), + migrations.AddField( + model_name='applycommandticket', + name='apply_from_session', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='terminal.session', verbose_name='Session'), + ), + migrations.AddField( + model_name='applycommandticket', + name='apply_run_user', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Run user'), + ), + migrations.AddField( + model_name='applyassetticket', + name='apply_assets', + field=models.ManyToManyField(to='assets.asset', verbose_name='Asset'), + ), + migrations.AddField( + model_name='applyassetticket', + name='apply_nodes', + field=models.ManyToManyField(to='assets.node', verbose_name='Node'), ), ] diff --git a/apps/tickets/migrations/0003_auto_20200804_1551.py b/apps/tickets/migrations/0003_auto_20200804_1551.py deleted file mode 100644 index 936dbc5bb..000000000 --- a/apps/tickets/migrations/0003_auto_20200804_1551.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-08-04 07:51 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0002_auto_20200728_1146'), - ] - - operations = [ - migrations.AlterField( - model_name='ticket', - name='assignee_display', - field=models.CharField(blank=True, default='', max_length=128, null=True, verbose_name='Assignee display name'), - ), - ] diff --git a/apps/tickets/migrations/0004_ticket_comment.py b/apps/tickets/migrations/0004_ticket_comment.py deleted file mode 100644 index c30776eb9..000000000 --- a/apps/tickets/migrations/0004_ticket_comment.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.13 on 2020-09-07 11:10 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0003_auto_20200804_1551'), - ] - - operations = [ - migrations.AddField( - model_name='ticket', - name='comment', - field=models.TextField(blank=True, default='', max_length=128, verbose_name='Comment'), - ), - ] diff --git a/apps/tickets/migrations/0005_ticket_meta_confirmed_system_users.py b/apps/tickets/migrations/0005_ticket_meta_confirmed_system_users.py deleted file mode 100644 index dd8fb686a..000000000 --- a/apps/tickets/migrations/0005_ticket_meta_confirmed_system_users.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by BaiJiangjie 2020-09-29 18:31 - -from django.db import migrations - - -def migrate_ticket_meta_confirmed_system_user_to_confirmed_system_users(apps, schema_editor): - ticket_model = apps.get_model("tickets", "Ticket") - tickets = ticket_model.origin_objects.all() - - for ticket in tickets: - meta = ticket.meta - confirmed_system_user = meta.get('confirmed_system_user') - if confirmed_system_user: - confirmed_system_users = [confirmed_system_user] - else: - confirmed_system_users = [] - meta.update({ - 'confirmed_system_users': confirmed_system_users - }) - ticket.meta = meta - ticket.save() - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0004_ticket_comment'), - ] - operations = [ - migrations.RunPython(migrate_ticket_meta_confirmed_system_user_to_confirmed_system_users) - ] diff --git a/apps/tickets/migrations/0006_auto_20201023_1628.py b/apps/tickets/migrations/0006_auto_20201023_1628.py deleted file mode 100644 index 55498d578..000000000 --- a/apps/tickets/migrations/0006_auto_20201023_1628.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.13 on 2020-10-23 08:28 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0005_ticket_meta_confirmed_system_users'), - ] - - operations = [ - migrations.AlterField( - model_name='ticket', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - ] diff --git a/apps/tickets/migrations/0007_auto_20201224_1821.py b/apps/tickets/migrations/0007_auto_20201224_1821.py deleted file mode 100644 index 31645b00f..000000000 --- a/apps/tickets/migrations/0007_auto_20201224_1821.py +++ /dev/null @@ -1,187 +0,0 @@ -# Generated by Django 3.1 on 2020-12-24 10:21 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion -import common.db.encoder - -TICKET_TYPE_APPLY_ASSET = 'apply_asset' - - -def migrate_field_type(tp): - if tp == 'request_asset': - return TICKET_TYPE_APPLY_ASSET - return tp - - -def migrate_field_meta(tp, old_meta): - if tp != TICKET_TYPE_APPLY_ASSET or not old_meta: - return old_meta - old_meta_hostname = old_meta.get('hostname') - old_meta_system_user = old_meta.get('system_user') - new_meta = { - 'apply_ip_group': old_meta.get('ips', []), - 'apply_hostname_group': [old_meta_hostname] if old_meta_hostname else [], - 'apply_system_user_group': [old_meta_system_user] if old_meta_system_user else [], - 'apply_actions': old_meta.get('actions'), - 'apply_actions_display': [], - 'apply_date_start': old_meta.get('date_start'), - 'apply_date_expired': old_meta.get('date_expired'), - - 'approve_assets': old_meta.get('confirmed_assets', []), - 'approve_assets_display': [], - 'approve_system_users': old_meta.get('confirmed_system_users', []), - 'approve_system_users_display': [], - 'approve_actions': old_meta.get('actions'), - 'approve_actions_display': [], - 'approve_date_start': old_meta.get('date_start'), - 'approve_date_expired': old_meta.get('date_expired'), - } - return new_meta - - -ACTION_OPEN = 'open' -ACTION_CLOSE = 'close' -STATUS_OPEN = 'open' -STATUS_CLOSED = 'closed' - - -def migrate_field_action(old_action, old_status): - if old_action: - return old_action - if old_status == STATUS_OPEN: - return ACTION_OPEN - if old_status == STATUS_CLOSED: - return ACTION_CLOSE - - -def migrate_field_assignees_display(assignees_display): - if not assignees_display: - return [] - assignees_display = assignees_display.split(', ') - return assignees_display - - -def migrate_tickets_fields_name(apps, schema_editor): - ticket_model = apps.get_model("tickets", "Ticket") - tickets = ticket_model.origin_objects.all() - - for ticket in tickets: - ticket.applicant = ticket.user - ticket.applicant_display = ticket.user_display - ticket.processor = ticket.assignee - ticket.processor_display = ticket.assignee_display - ticket.assignees_display_new = migrate_field_assignees_display(ticket.assignees_display) - ticket.action = migrate_field_action(ticket.action, ticket.status) - ticket.type = migrate_field_type(ticket.type) - ticket.meta = migrate_field_meta(ticket.type, ticket.meta) - ticket.meta['body'] = ticket.body - - fields = [ - 'applicant', 'applicant_display', 'processor', 'processor_display', - 'assignees_display_new', 'action', 'type', 'meta' - ] - ticket_model.origin_objects.bulk_update(tickets, fields) - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('tickets', '0006_auto_20201023_1628'), - ] - - operations = [ - # model ticket - migrations.AddField( - model_name='ticket', - name='applicant', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='applied_tickets', to=settings.AUTH_USER_MODEL, verbose_name='Applicant'), - ), - migrations.AddField( - model_name='ticket', - name='applicant_display', - field=models.CharField(default='', max_length=256, verbose_name='Applicant display'), - ), - migrations.AddField( - model_name='ticket', - name='processor', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='processed_tickets', to=settings.AUTH_USER_MODEL, verbose_name='Processor'), - ), - migrations.AddField( - model_name='ticket', - name='processor_display', - field=models.CharField(blank=True, default='', max_length=256, null=True, verbose_name='Processor display'), - ), - migrations.AddField( - model_name='ticket', - name='assignees_display_new', - field=models.JSONField(default=list, encoder=common.db.encoder.ModelJSONFieldEncoder, verbose_name='Assignees display'), - ), - migrations.AlterField( - model_name='ticket', - name='assignees', - field=models.ManyToManyField(related_name='assigned_tickets', to=settings.AUTH_USER_MODEL, verbose_name='Assignees'), - ), - migrations.AlterField( - model_name='ticket', - name='meta', - field=models.JSONField(default=dict, encoder=common.db.encoder.ModelJSONFieldEncoder, verbose_name='Meta'), - ), - migrations.AlterField( - model_name='ticket', - name='type', - field=models.CharField(choices=[('general', 'General'), ('login_confirm', 'Login confirm'), ('apply_asset', 'Apply for asset'), ('apply_application', 'Apply for application')], default='general', max_length=64, verbose_name='Type'), - ), - migrations.AlterField( - model_name='ticket', - name='action', - field=models.CharField(choices=[('open', 'Open'), ('approve', 'Approve'), ('reject', 'Reject'), ('close', 'Close')], default='open', max_length=16, verbose_name='Action'), - ), - migrations.AlterField( - model_name='ticket', - name='status', - field=models.CharField(choices=[('open', 'Open'), ('closed', 'Closed')], default='open', max_length=16, verbose_name='Status'), - ), - migrations.RunPython(migrate_tickets_fields_name), - migrations.RemoveField( - model_name='ticket', - name='user', - ), - migrations.RemoveField( - model_name='ticket', - name='user_display', - ), - migrations.RemoveField( - model_name='ticket', - name='assignee', - ), - migrations.RemoveField( - model_name='ticket', - name='assignee_display', - ), - migrations.RemoveField( - model_name='ticket', - name='body', - ), - migrations.RemoveField( - model_name='ticket', - name='assignees_display', - ), - migrations.RenameField( - model_name='ticket', - old_name='assignees_display_new', - new_name='assignees_display', - ), - migrations.AlterModelManagers( - name='ticket', - managers=[ - ], - ), - # model comment - migrations.AlterField( - model_name='comment', - name='user_display', - field=models.CharField(max_length=256, verbose_name='User display name'), - ), - ] diff --git a/apps/tickets/migrations/0008_auto_20210311_1113.py b/apps/tickets/migrations/0008_auto_20210311_1113.py deleted file mode 100644 index be959ba0e..000000000 --- a/apps/tickets/migrations/0008_auto_20210311_1113.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2021-03-11 03:13 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0007_auto_20201224_1821'), - ] - - operations = [ - migrations.AlterField( - model_name='ticket', - name='type', - field=models.CharField(choices=[('general', 'General'), ('login_confirm', 'Login confirm'), ('apply_asset', 'Apply for asset'), ('apply_application', 'Apply for application'), ('login_asset_confirm', 'Login asset confirm')], default='general', max_length=64, verbose_name='Type'), - ), - ] diff --git a/apps/tickets/migrations/0009_auto_20210426_1720.py b/apps/tickets/migrations/0009_auto_20210426_1720.py deleted file mode 100644 index e584c2560..000000000 --- a/apps/tickets/migrations/0009_auto_20210426_1720.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2021-04-26 09:20 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0008_auto_20210311_1113'), - ] - - operations = [ - migrations.AlterField( - model_name='ticket', - name='type', - field=models.CharField(choices=[('general', 'General'), ('login_confirm', 'Login confirm'), ('apply_asset', 'Apply for asset'), ('apply_application', 'Apply for application'), ('login_asset_confirm', 'Login asset confirm'), ('command_confirm', 'Command confirm')], default='general', max_length=64, verbose_name='Type'), - ), - ] diff --git a/apps/tickets/migrations/0010_auto_20210812_1618.py b/apps/tickets/migrations/0010_auto_20210812_1618.py deleted file mode 100644 index e858f9acf..000000000 --- a/apps/tickets/migrations/0010_auto_20210812_1618.py +++ /dev/null @@ -1,233 +0,0 @@ -# Generated by Django 3.1.6 on 2021-08-12 08:18 - -import common.db.encoder -from django.conf import settings -from django.db import migrations, models, transaction -import django.db.models.deletion -import uuid - -from tickets.const import TicketType, TicketApprovalStrategy - -ticket_assignee_m2m = list() - - -def get_ticket_assignee_m2m_info(apps, schema_editor): - ticket_model = apps.get_model("tickets", "Ticket") - for i in ticket_model.objects.only('id', 'assignees', 'action', 'created_by'): - ticket_assignee_m2m.append((i.id, list(i.assignees.values_list('id', flat=True)), i.action, i.created_by)) - - -def update_ticket_process_meta_state_status(apps, schema_editor): - ticket_model = apps.get_model("tickets", "Ticket") - updates = list() - with transaction.atomic(): - for instance in ticket_model.objects.all(): - if instance.action == 'open': - state = 'notified' - elif instance.action == 'approve': - state = 'approved' - elif instance.action == 'reject': - state = 'rejected' - else: - state = 'closed' - instance.process_map = [{ - 'state': state, - 'approval_level': 1, - 'approval_date': str(instance.date_updated), - 'processor': instance.processor.id if instance.processor else '', - 'processor_display': instance.processor_display if instance.processor_display else '', - 'assignees': list(instance.assignees.values_list('id', flat=True)) if instance.assignees else [], - 'assignees_display': instance.assignees_display if instance.assignees_display else [] - }, ] - instance.state = state - instance.meta['apply_assets'] = instance.meta.pop('approve_assets', []) - instance.meta['apply_assets_display'] = instance.meta.pop('approve_assets_display', []) - instance.meta['apply_actions'] = instance.meta.pop('approve_actions', 0) - instance.meta['apply_actions_display'] = instance.meta.pop('approve_actions_display', []) - instance.meta['apply_applications'] = instance.meta.pop('approve_applications', []) - instance.meta['apply_applications_display'] = instance.meta.pop('approve_applications_display', []) - instance.meta['apply_system_users'] = instance.meta.pop('approve_system_users', []) - instance.meta['apply_system_users_display'] = instance.meta.pop('approve_system_users_display', []) - updates.append(instance) - ticket_model.objects.bulk_update(updates, ['process_map', 'state', 'meta', 'status']) - - -def create_step_and_assignee(apps, schema_editor): - ticket_step_model = apps.get_model("tickets", "TicketStep") - ticket_assignee_model = apps.get_model("tickets", "TicketAssignee") - creates = list() - with transaction.atomic(): - for ticket_id, assignees, action, created_by in ticket_assignee_m2m: - if action == 'open': - state = 'notified' - elif action == 'approve': - state = 'approved' - else: - state = 'rejected' - step_instance = ticket_step_model.objects.create(ticket_id=ticket_id, state=state, created_by=created_by) - for assignee_id in assignees: - creates.append( - ticket_assignee_model( - step=step_instance, assignee_id=assignee_id, state=state, created_by=created_by - ) - ) - ticket_assignee_model.objects.bulk_create(creates) - - -def create_ticket_flow_and_approval_rule(apps, schema_editor): - user_model = apps.get_model("users", "User") - org_id = '00000000-0000-0000-0000-000000000000' - ticket_flow_model = apps.get_model("tickets", "TicketFlow") - approval_rule_model = apps.get_model("tickets", "ApprovalRule") - super_user = user_model.objects.filter(role='Admin') - assignees_display = ['{0.name}({0.username})'.format(i) for i in super_user] - with transaction.atomic(): - for ticket_type in [TicketType.apply_asset, 'apply_application']: - ticket_flow_instance = ticket_flow_model.objects.create(created_by='System', type=ticket_type, org_id=org_id) - approval_rule_instance = approval_rule_model.objects.create(strategy=TicketApprovalStrategy.super_admin, assignees_display=assignees_display) - approval_rule_instance.assignees.set(list(super_user)) - ticket_flow_instance.rules.set([approval_rule_instance, ]) - - -class Migration(migrations.Migration): - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('tickets', '0009_auto_20210426_1720'), - ] - - operations = [ - migrations.CreateModel( - name='ApprovalRule', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('level', models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1, - verbose_name='Approve level')), - ('strategy', models.CharField( - choices=[('super_admin', 'Super admin'), ('org_admin', 'Org admin'), ('super_org_admin', 'Super admin and org admin'), - ('custom_user', 'Custom user')], - default='super_admin', max_length=64, verbose_name='Approve strategy')), - ('assignees_display', models.JSONField(default=list, encoder=common.db.encoder.ModelJSONFieldEncoder, - verbose_name='Assignees display')), - ('assignees', - models.ManyToManyField(related_name='assigned_ticket_flow_approval_rule', to=settings.AUTH_USER_MODEL, - verbose_name='Assignees')), - ], - options={ - 'verbose_name': 'Ticket flow approval rule', - }, - ), - migrations.RunPython(get_ticket_assignee_m2m_info), - migrations.AddField( - model_name='ticket', - name='process_map', - field=models.JSONField(default=list, encoder=common.db.encoder.ModelJSONFieldEncoder, - verbose_name='Process'), - ), - migrations.AddField( - model_name='ticket', - name='state', - field=models.CharField( - choices=[('open', 'Open'), ('approved', 'Approved'), ('rejected', 'Rejected'), ('closed', 'Closed')], - default='open', max_length=16, verbose_name='State'), - ), - migrations.RunPython(update_ticket_process_meta_state_status), - migrations.RemoveField( - model_name='ticket', - name='action', - ), - migrations.RemoveField( - model_name='ticket', - name='assignees', - ), - migrations.RemoveField( - model_name='ticket', - name='assignees_display', - ), - migrations.RemoveField( - model_name='ticket', - name='processor', - ), - migrations.RemoveField( - model_name='ticket', - name='processor_display', - ), - migrations.AddField( - model_name='ticket', - name='approval_step', - field=models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1, - verbose_name='Approval step'), - ), - migrations.CreateModel( - name='TicketStep', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('level', models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1, - verbose_name='Approve level')), - ('state', models.CharField( - choices=[('notified', 'Notified'), ('approved', 'Approved'), ('rejected', 'Rejected')], - default='notified', max_length=64)), - ('ticket', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_steps', - to='tickets.ticket', verbose_name='Ticket')), - ], - options={ - 'abstract': False, - }, - ), - migrations.CreateModel( - name='TicketFlow', - fields=[ - ('org_id', - models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('type', models.CharField(choices=[('general', 'General'), ('login_confirm', 'Login confirm'), - ('apply_asset', 'Apply for asset'), - ('apply_application', 'Apply for application'), - ('login_asset_confirm', 'Login asset confirm'), - ('command_confirm', 'Command confirm')], default='general', - max_length=64, verbose_name='Type')), - ('approval_level', models.SmallIntegerField(choices=[(1, 'One level'), (2, 'Two level')], default=1, - verbose_name='Approve level')), - ('rules', models.ManyToManyField(related_name='ticket_flows', to='tickets.ApprovalRule')), - ], - options={ - 'verbose_name': 'Ticket flow', - }, - ), - migrations.CreateModel( - name='TicketAssignee', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created 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')), - ('state', models.CharField( - choices=[('notified', 'Notified'), ('approved', 'Approved'), ('rejected', 'Rejected')], - default='notified', max_length=64)), - ('assignee', - models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_assignees', - to=settings.AUTH_USER_MODEL, verbose_name='Assignee')), - ('step', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='ticket_assignees', - to='tickets.ticketstep')), - ], - options={ - 'verbose_name': 'Ticket assignee', - }, - ), - migrations.RunPython(create_step_and_assignee), - migrations.RunPython(create_ticket_flow_and_approval_rule), - migrations.AddField( - model_name='ticket', - name='flow', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='tickets', - to='tickets.ticketflow', verbose_name='TicketFlow'), - ), - ] diff --git a/apps/tickets/migrations/0011_remove_approvalrule_assignees_display.py b/apps/tickets/migrations/0011_remove_approvalrule_assignees_display.py deleted file mode 100644 index f709114d8..000000000 --- a/apps/tickets/migrations/0011_remove_approvalrule_assignees_display.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-15 09:56 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0010_auto_20210812_1618'), - ] - - operations = [ - migrations.RemoveField( - model_name='approvalrule', - name='assignees_display', - ), - ] diff --git a/apps/tickets/migrations/0012_ticketsession.py b/apps/tickets/migrations/0012_ticketsession.py deleted file mode 100644 index ac4afdad8..000000000 --- a/apps/tickets/migrations/0012_ticketsession.py +++ /dev/null @@ -1,24 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-29 08:19 - -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('terminal', '0042_auto_20211229_1619'), - ('tickets', '0011_remove_approvalrule_assignees_display'), - ] - - operations = [ - migrations.CreateModel( - name='TicketSession', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('session', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, related_name='ticket_relation', to='terminal.session')), - ('ticket', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, related_name='session_relation', to='tickets.ticket')), - ], - options={'verbose_name': 'Ticket session relation'}, - ), - ] diff --git a/apps/tickets/migrations/0013_ticket_serial_num.py b/apps/tickets/migrations/0013_ticket_serial_num.py deleted file mode 100644 index bad05a7f6..000000000 --- a/apps/tickets/migrations/0013_ticket_serial_num.py +++ /dev/null @@ -1,46 +0,0 @@ -# Generated by Django 3.1.13 on 2022-01-10 07:37 - -from django.db import migrations, models - -from common.utils.timezone import as_current_tz - - -def fill_ticket_serial_number(apps, schema_editor): - Ticket = apps.get_model('tickets', 'Ticket') - tickets = Ticket.objects.all().order_by('date_created') - - curr_day = '00000000' - curr_num = 1 - - print(f'\n\tFill ticket serial number ... ') - for ticket in tickets: - # 跑这个脚本的时候,所有 ticket.serial_num == null - date_created = as_current_tz(ticket.date_created) - date_str = date_created.strftime('%Y%m%d') - if date_str != curr_day: - curr_day = date_str - curr_num = 1 - - ticket.serial_num = curr_day + '%04d' % curr_num - curr_num += 1 - - Ticket.objects.bulk_update(tickets, fields=('serial_num',)) - - -class Migration(migrations.Migration): - dependencies = [ - ('tickets', '0012_ticketsession'), - ] - - operations = [ - migrations.AddField( - model_name='ticket', - name='serial_num', - field=models.CharField(max_length=128, null=True, verbose_name='Serial number'), - ), - migrations.RunPython(fill_ticket_serial_number), - migrations.AlterUniqueTogether( - name='ticket', - unique_together={('serial_num',)}, - ), - ] diff --git a/apps/tickets/migrations/0014_auto_20220217_2135.py b/apps/tickets/migrations/0014_auto_20220217_2135.py deleted file mode 100644 index 246ef1bed..000000000 --- a/apps/tickets/migrations/0014_auto_20220217_2135.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.13 on 2022-02-17 13:35 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0013_ticket_serial_num'), - ] - - operations = [ - migrations.AlterModelOptions( - name='comment', - options={'ordering': ('date_created',), 'verbose_name': 'Comment'}, - ), - migrations.AlterModelOptions( - name='ticket', - options={'ordering': ('-date_created',), 'verbose_name': 'Ticket'}, - ), - migrations.AlterModelOptions( - name='ticketstep', - options={'verbose_name': 'Ticket step'}, - ), - ] diff --git a/apps/tickets/migrations/0015_superticket.py b/apps/tickets/migrations/0015_superticket.py deleted file mode 100644 index 6d2c526b7..000000000 --- a/apps/tickets/migrations/0015_superticket.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1.14 on 2022-02-28 10:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0014_auto_20220217_2135'), - ] - - operations = [ - migrations.CreateModel( - name='SuperTicket', - fields=[ - ], - options={ - 'verbose_name': 'Super ticket', - 'proxy': True, - 'indexes': [], - 'constraints': [], - }, - bases=('tickets.ticket',), - ), - ] diff --git a/apps/tickets/migrations/0016_auto_20220609_1758.py b/apps/tickets/migrations/0016_auto_20220609_1758.py deleted file mode 100644 index 73d5b21c7..000000000 --- a/apps/tickets/migrations/0016_auto_20220609_1758.py +++ /dev/null @@ -1,190 +0,0 @@ -# Generated by Django 3.1.14 on 2022-06-09 09:58 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('terminal', '0049_endpoint_redis_port'), - ('assets', '0090_auto_20220412_1145'), - ('applications', '0020_auto_20220316_2028'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('tickets', '0015_superticket'), - ] - - operations = [ - migrations.CreateModel( - name='ApplyLoginTicket', - fields=[ - ('ticket_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='tickets.ticket')), - ('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_datetime', models.DateTimeField(null=True, verbose_name='Login Date')), - ], - options={ - 'abstract': False, - 'verbose_name': 'Apply Login Ticket' - }, - bases=('tickets.ticket',), - ), - migrations.RemoveField( - model_name='ticket', - name='process_map', - ), - migrations.AddField( - model_name='comment', - name='state', - field=models.CharField(max_length=16, null=True), - ), - migrations.AddField( - model_name='comment', - name='type', - field=models.CharField(choices=[('state', 'State'), ('common', 'common')], default='common', max_length=16, - verbose_name='Type'), - ), - migrations.AddField( - model_name='ticket', - name='rel_snapshot', - field=models.JSONField(default=dict, verbose_name='Relation snapshot'), - ), - migrations.AddField( - model_name='ticketstep', - name='status', - field=models.CharField(choices=[('pending', 'Pending'), ('active', 'Active'), ('closed', 'Closed')], - default='pending', max_length=16), - ), - migrations.AlterField( - model_name='ticket', - name='state', - field=models.CharField(choices=[('pending', 'Open'), ('approved', 'Approved'), ('rejected', 'Rejected'), - ('closed', 'Cancel')], default='pending', - max_length=16, verbose_name='State'), - ), - migrations.AlterField( - model_name='ticket', - name='status', - field=models.CharField(choices=[('open', 'Open'), ('closed', 'Finished')], default='open', max_length=16, - verbose_name='Status'), - ), - migrations.AlterField( - model_name='ticketassignee', - name='state', - field=models.CharField(choices=[('pending', 'Open'), ('approved', 'Approved'), ('rejected', 'Rejected'), - ('closed', 'Cancel')], default='pending', - max_length=64), - ), - migrations.AlterField( - model_name='ticketstep', - name='state', - field=models.CharField(choices=[('pending', 'Pending'), ('approved', 'Approved'), ('rejected', 'Rejected'), - ('closed', 'Closed')], default='pending', - max_length=64, verbose_name='State'), - ), - migrations.CreateModel( - name='ApplyLoginAssetTicket', - fields=[ - ('ticket_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='tickets.ticket')), - ('apply_login_asset', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.asset', - verbose_name='Login asset')), - ('apply_login_system_user', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.systemuser', - verbose_name='Login system user')), - ('apply_login_user', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, - verbose_name='Login user')), - ], - options={ - 'abstract': False, - 'verbose_name': 'Apply Login Asset Ticket' - }, - bases=('tickets.ticket',), - ), - migrations.CreateModel( - name='ApplyCommandTicket', - fields=[ - ('ticket_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='tickets.ticket')), - ('apply_run_command', models.CharField(max_length=4096, verbose_name='Run command')), - ('apply_run_asset', models.CharField(max_length=128, verbose_name='Run asset')), - ('apply_from_cmd_filter', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.commandfilter', - verbose_name='From cmd filter')), - ('apply_from_cmd_filter_rule', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, - to='assets.commandfilterrule', verbose_name='From cmd filter rule')), - ('apply_from_session', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='terminal.session', - verbose_name='Session')), - ('apply_run_system_user', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.systemuser', - verbose_name='Run system user')), - ('apply_run_user', - models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, - verbose_name='Run user')), - ], - options={ - 'abstract': False, - 'verbose_name': 'Apply Command Ticket' - }, - bases=('tickets.ticket',), - ), - migrations.CreateModel( - name='ApplyAssetTicket', - fields=[ - ('ticket_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='tickets.ticket')), - ('apply_permission_name', models.CharField(max_length=128, verbose_name='Permission name')), - ('apply_actions', models.IntegerField( - choices=[(255, 'All'), (1, 'Connect'), (2, 'Upload file'), (4, 'Download file'), - (6, 'Upload download'), (8, 'Clipboard copy'), (16, 'Clipboard paste'), - (24, 'Clipboard copy paste')], default=255, verbose_name='Actions')), - ('apply_date_start', models.DateTimeField(null=True, verbose_name='Date start')), - ('apply_date_expired', models.DateTimeField(null=True, verbose_name='Date expired')), - ('apply_assets', models.ManyToManyField(to='assets.Asset', verbose_name='Apply assets')), - ('apply_nodes', models.ManyToManyField(to='assets.Node', verbose_name='Apply nodes')), - ('apply_system_users', - models.ManyToManyField(to='assets.SystemUser', verbose_name='Apply system users')), - ], - options={ - 'abstract': False, - }, - bases=('tickets.ticket',), - ), - migrations.CreateModel( - name='ApplyApplicationTicket', - fields=[ - ('ticket_ptr', - models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, - primary_key=True, serialize=False, to='tickets.ticket')), - ('apply_permission_name', models.CharField(max_length=128, verbose_name='Permission name')), - ('apply_category', - models.CharField(choices=[('db', 'Database'), ('remote_app', 'Remote app'), ('cloud', 'Cloud')], - max_length=16, verbose_name='Category')), - ('apply_type', models.CharField( - choices=[('mysql', 'MySQL'), ('mariadb', 'MariaDB'), ('oracle', 'Oracle'), - ('postgresql', 'PostgreSQL'), ('sqlserver', 'SQLServer'), ('redis', 'Redis'), - ('mongodb', 'MongoDB'), ('chrome', 'Chrome'), ('mysql_workbench', 'MySQL Workbench'), - ('vmware_client', 'vSphere Client'), ('custom', 'Custom'), ('k8s', 'Kubernetes')], - max_length=16, verbose_name='Type')), - ('apply_date_start', models.DateTimeField(null=True, verbose_name='Date start')), - ('apply_date_expired', models.DateTimeField(null=True, verbose_name='Date expired')), - ('apply_applications', - models.ManyToManyField(to='applications.Application', verbose_name='Apply applications')), - ('apply_system_users', - models.ManyToManyField(to='assets.SystemUser', verbose_name='Apply system users')), - ], - options={ - 'abstract': False, - }, - bases=('tickets.ticket',), - ), - ] diff --git a/apps/tickets/migrations/0017_auto_20220623_1027.py b/apps/tickets/migrations/0017_auto_20220623_1027.py deleted file mode 100644 index ba2351d65..000000000 --- a/apps/tickets/migrations/0017_auto_20220623_1027.py +++ /dev/null @@ -1,334 +0,0 @@ -# Generated by Django 3.1.14 on 2022-06-23 02:27 - -import re -from datetime import datetime -from collections import defaultdict - -from django.utils import timezone as dj_timezone -from django.db import migrations - -from tickets.const import TicketType - -pt = re.compile(r'(\w+)\((\w+)\)') - - -def time_conversion(t): - if not t: - return - try: - return datetime.strptime(t, '%Y-%m-%d %H:%M:%S'). \ - astimezone(dj_timezone.get_current_timezone()) - except Exception: - return - - -nodes_dict = defaultdict(set) -assets_dict = defaultdict(set) -system_users_dict = defaultdict(set) -apps_dict = defaultdict(set) -global_inited = {} - - -def init_global_dict(apps): - if global_inited: - return - node_model = apps.get_model('assets', 'Node') - asset_model = apps.get_model('assets', 'Asset') - system_user_model = apps.get_model('assets', 'SystemUser') - application_model = apps.get_model('applications', 'Application') - - node_qs = node_model.objects.values('id', 'org_id') - asset_qs = asset_model.objects.values('id', 'org_id') - system_user_qs = system_user_model.objects.values('id', 'org_id') - app_qs = application_model.objects.values('id', 'org_id') - - for d, qs in [ - (nodes_dict, node_qs), - (assets_dict, asset_qs), - (system_users_dict, system_user_qs), - (apps_dict, app_qs) - ]: - for i in qs: - _id = str(i['id']) - org_id = str(i['org_id']) - d[org_id].add(_id) - global_inited['inited'] = True - - -def apply_asset_migrate(apps, *args): - init_global_dict(apps) - - ticket_model = apps.get_model('tickets', 'Ticket') - tickets = ticket_model.objects.filter(type=TicketType.apply_asset) - ticket_apply_asset_model = apps.get_model('tickets', 'ApplyAssetTicket') - - for instance in tickets: - meta = instance.meta - org_id = instance.org_id - apply_actions = meta.get('apply_actions') - - # 数据库中数据结构有问题,可能是 list,可能是 int - if isinstance(apply_actions, list): - apply_actions = Action.choices_to_value(value=apply_actions) - elif isinstance(apply_actions, int): - apply_actions = apply_actions - else: - apply_actions = 0 - - data = { - 'ticket_ptr_id': instance.pk, - 'apply_permission_name': meta.get('apply_permission_name', ''), - 'apply_date_start': time_conversion(meta.get('apply_date_start')), - 'apply_date_expired': time_conversion(meta.get('apply_date_expired')), - 'apply_actions': apply_actions, - } - - child = ticket_apply_asset_model(**data) - child.__dict__.update(instance.__dict__) - child.save() - - apply_nodes = list(set(meta.get('apply_nodes', [])) & nodes_dict[org_id]) - apply_assets = list(set(meta.get('apply_assets', [])) & assets_dict[org_id]) - apply_system_users = list(set(meta.get('apply_system_users', [])) & system_users_dict[org_id]) - child.apply_nodes.set(apply_nodes) - child.apply_assets.set(apply_assets) - child.apply_system_users.set(apply_system_users) - - if (not apply_nodes and not apply_assets) or not apply_system_users: - continue - - rel_snapshot = { - 'applicant': instance.applicant_display, - 'apply_nodes': meta.get('apply_nodes_display', []), - 'apply_assets': meta.get('apply_assets_display', []), - 'apply_system_users': meta.get('apply_system_users_display', []), - } - instance.rel_snapshot = rel_snapshot - instance.save(update_fields=['rel_snapshot']) - - -def apply_application_migrate(apps, *args): - init_global_dict(apps) - - ticket_model = apps.get_model('tickets', 'Ticket') - tickets = ticket_model.objects.filter(type='apply_application') - ticket_apply_app_model = apps.get_model('tickets', 'ApplyApplicationTicket') - - for instance in tickets: - meta = instance.meta - org_id = instance.org_id - data = { - 'ticket_ptr_id': instance.pk, - 'apply_permission_name': meta.get('apply_permission_name', ''), - 'apply_category': meta.get('apply_category'), - 'apply_type': meta.get('apply_type'), - 'apply_date_start': time_conversion(meta.get('apply_date_start')), - 'apply_date_expired': time_conversion(meta.get('apply_date_expired')), - } - child = ticket_apply_app_model(**data) - child.__dict__.update(instance.__dict__) - child.save() - - apply_applications = list(set(meta.get('apply_applications', [])) & apps_dict[org_id]) - apply_system_users = list(set(meta.get('apply_system_users', [])) & system_users_dict[org_id]) - if not apply_applications or not apply_system_users: - continue - child.apply_applications.set(apply_applications) - child.apply_system_users.set(apply_system_users) - - rel_snapshot = { - 'applicant': instance.applicant_display, - 'apply_applications': meta.get('apply_applications_display', []), - 'apply_system_users': meta.get('apply_system_users_display', []), - } - instance.rel_snapshot = rel_snapshot - instance.save(update_fields=['rel_snapshot']) - - -def login_confirm_migrate(apps, *args): - ticket_model = apps.get_model('tickets', 'Ticket') - tickets = ticket_model.objects.filter(type=TicketType.login_confirm) - ticket_apply_login_model = apps.get_model('tickets', 'ApplyLoginTicket') - - for instance in tickets: - meta = instance.meta - data = { - 'ticket_ptr_id': instance.pk, - 'apply_login_ip': meta.get('apply_login_ip'), - 'apply_login_city': meta.get('apply_login_city'), - 'apply_login_datetime': time_conversion(meta.get('apply_login_datetime')), - } - rel_snapshot = { - 'applicant': instance.applicant_display - } - instance.rel_snapshot = rel_snapshot - instance.save(update_fields=['rel_snapshot']) - child = ticket_apply_login_model(**data) - child.__dict__.update(instance.__dict__) - child.save() - - -def analysis_instance_name(name: str): - if not name: - return None - matched = pt.match(name) - if not matched: - return None - return matched.groups() - - -def login_asset_confirm_migrate(apps, *args): - user_model = apps.get_model('users', 'User') - asset_model = apps.get_model('assets', 'Asset') - system_user_model = apps.get_model('assets', 'SystemUser') - ticket_model = apps.get_model('tickets', 'Ticket') - tickets = ticket_model.objects.filter(type=TicketType.login_asset_confirm) - ticket_apply_login_asset_model = apps.get_model('tickets', 'ApplyLoginAssetTicket') - - for instance in tickets: - meta = instance.meta - - name_username = analysis_instance_name(meta.get('apply_login_user')) - apply_login_user = user_model.objects.filter( - name=name_username[0], - username=name_username[1] - ).first() if name_username else None - - hostname_ip = analysis_instance_name(meta.get('apply_login_asset')) - apply_login_asset = asset_model.objects.filter( - org_id=instance.org_id, - hostname=hostname_ip[0], - ip=hostname_ip[1] - ).first() if hostname_ip else None - - name_username = analysis_instance_name(meta.get('apply_login_system_user')) - apply_login_system_user = system_user_model.objects.filter( - org_id=instance.org_id, - name=name_username[0], - username=name_username[1] - ).first() if name_username else None - - data = { - 'ticket_ptr_id': instance.pk, - 'apply_login_user': apply_login_user, - 'apply_login_asset': apply_login_asset, - 'apply_login_system_user': apply_login_system_user, - } - child = ticket_apply_login_asset_model(**data) - child.__dict__.update(instance.__dict__) - child.save() - - rel_snapshot = { - 'applicant': instance.applicant_display, - 'apply_login_user': meta.get('apply_login_user', ''), - 'apply_login_asset': meta.get('apply_login_asset', ''), - 'apply_login_system_user': meta.get('apply_login_system_user', ''), - } - instance.rel_snapshot = rel_snapshot - instance.save(update_fields=['rel_snapshot']) - - -def command_confirm_migrate(apps, *args): - user_model = apps.get_model('users', 'User') - asset_model = apps.get_model('assets', 'Asset') - system_user_model = apps.get_model('assets', 'SystemUser') - ticket_model = apps.get_model('tickets', 'Ticket') - session_model = apps.get_model('terminal', 'Session') - command_filter_model = apps.get_model('assets', 'CommandFilter') - command_filter_rule_model = apps.get_model('assets', 'CommandFilterRule') - - tickets = ticket_model.objects.filter(type=TicketType.command_confirm) - session_ids = tickets.values_list('meta__apply_from_session_id', flat=True) - session_ids = session_model.objects.filter(id__in=list(session_ids)).values_list('id', flat=True) - session_ids = [str(i) for i in session_ids] - command_filter_ids = tickets.values_list('meta__apply_from_cmd_filter_id', flat=True) - command_filter_ids = command_filter_model.objects\ - .filter(id__in=list(command_filter_ids))\ - .values_list('id', flat=True) - command_filter_ids = [str(i) for i in command_filter_ids] - command_filter_rule_ids = tickets.values_list('meta__apply_from_cmd_filter_rule_id', flat=True) - command_filter_rule_ids = command_filter_rule_model.objects\ - .filter(id__in=list(command_filter_rule_ids))\ - .values_list('id', flat=True) - command_filter_rule_ids = [str(i) for i in command_filter_rule_ids] - - ticket_apply_command_model = apps.get_model('tickets', 'ApplyCommandTicket') - - for instance in tickets: - meta = instance.meta - - name_username = analysis_instance_name(meta.get('apply_run_user')) - apply_run_user = user_model.objects.filter( - name=name_username[0], username=name_username[1] - ).first() if name_username else None - - name_username = analysis_instance_name(meta.get('apply_run_system_user')) - apply_run_system_user = system_user_model.objects.filter( - org_id=instance.org_id, name=name_username[0], username=name_username[1] - ).first() if name_username else None - - apply_from_session_id = meta.get('apply_from_session_id') - apply_from_cmd_filter_id = meta.get('apply_from_cmd_filter_id') - apply_from_cmd_filter_rule_id = meta.get('apply_from_cmd_filter_rule_id') - - if apply_from_session_id not in session_ids: - apply_from_session_id = None - if apply_from_cmd_filter_id not in command_filter_ids: - apply_from_cmd_filter_id = None - if apply_from_cmd_filter_rule_id not in command_filter_rule_ids: - apply_from_cmd_filter_rule_id = None - - data = { - 'ticket_ptr_id': instance.pk, - 'apply_run_user': apply_run_user, - 'apply_run_asset': meta.get('apply_run_asset', ''), - 'apply_run_system_user': apply_run_system_user, - 'apply_run_command': meta.get('apply_run_command', '')[:4090], - 'apply_from_session_id': apply_from_session_id, - 'apply_from_cmd_filter_id': apply_from_cmd_filter_id, - 'apply_from_cmd_filter_rule_id': apply_from_cmd_filter_rule_id, - } - - rel_snapshot = { - 'applicant': instance.applicant_display, - 'apply_run_user': meta.get('apply_run_user', ''), - 'apply_run_system_user': meta.get('apply_run_system_user', ''), - 'apply_from_session': meta.get('apply_from_session_id', ''), - 'apply_from_cmd_filter': meta.get('apply_from_cmd_filter_id', ''), - 'apply_from_cmd_filter_rule': meta.get('apply_from_cmd_filter_rule_id', ''), - } - child = ticket_apply_command_model(**data) - child.__dict__.update(instance.__dict__) - child.save() - - instance.rel_snapshot = rel_snapshot - instance.save(update_fields=['rel_snapshot']) - - -def migrate_ticket_state(apps, *args): - ticket_model = apps.get_model('tickets', 'Ticket') - ticket_step_model = apps.get_model('tickets', 'TicketStep') - ticket_assignee_model = apps.get_model('tickets', 'TicketAssignee') - ticket_model.objects.filter(state='open').update(state='pending') - ticket_step_model.objects.filter(state='notified').update(state='pending') - ticket_assignee_model.objects.filter(state='notified').update(state='pending') - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0016_auto_20220609_1758'), - ] - - operations = [ - migrations.RunPython(migrate_ticket_state), - migrations.RunPython(apply_asset_migrate), - migrations.RunPython(apply_application_migrate), - migrations.RunPython(login_confirm_migrate), - migrations.RunPython(login_asset_confirm_migrate), - migrations.RunPython(command_confirm_migrate), - migrations.RemoveField( - model_name='ticket', - name='applicant_display', - ), - ] diff --git a/apps/tickets/migrations/0018_applyapplicationticket_apply_actions.py b/apps/tickets/migrations/0018_applyapplicationticket_apply_actions.py deleted file mode 100644 index a2890c82d..000000000 --- a/apps/tickets/migrations/0018_applyapplicationticket_apply_actions.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.2.14 on 2022-07-28 03:25 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('tickets', '0017_auto_20220623_1027'), - ] - - operations = [ - migrations.AddField( - model_name='applyapplicationticket', - name='apply_actions', - field=models.IntegerField( - choices=[ - (255, 'All'), (1, 'Connect'), (2, 'Upload file'), (4, 'Download file'), (6, 'Upload download'), - (8, 'Clipboard copy'), (16, 'Clipboard paste'), (24, 'Clipboard copy paste') - ], default=255, - verbose_name='Actions'), - ), - ] diff --git a/apps/tickets/migrations/0019_delete_applyapplicationticket.py b/apps/tickets/migrations/0019_delete_applyapplicationticket.py deleted file mode 100644 index d198f2228..000000000 --- a/apps/tickets/migrations/0019_delete_applyapplicationticket.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-16 08:29 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0018_applyapplicationticket_apply_actions'), - ] - - operations = [ - migrations.DeleteModel( - name='ApplyApplicationTicket', - ), - ] diff --git a/apps/tickets/migrations/0020_auto_20220817_1346.py b/apps/tickets/migrations/0020_auto_20220817_1346.py deleted file mode 100644 index a79bf727a..000000000 --- a/apps/tickets/migrations/0020_auto_20220817_1346.py +++ /dev/null @@ -1,87 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-17 05:46 - -import time - -from django.db import migrations, models - - -def migrate_system_to_account(apps, schema_editor): - apply_asset_ticket_model = apps.get_model('tickets', 'ApplyAssetTicket') - apply_command_ticket_model = apps.get_model('tickets', 'ApplyCommandTicket') - apply_login_asset_ticket_model = apps.get_model('tickets', 'ApplyLoginAssetTicket') - - model_system_user_account = ( - (apply_asset_ticket_model, 'apply_system_users', 'apply_accounts', True), - (apply_command_ticket_model, 'apply_run_system_user', 'apply_run_account', False), - (apply_login_asset_ticket_model, 'apply_login_system_user', 'apply_login_account', False), - ) - - print("\n Start migrate system user to account") - for model, old_field, new_field, m2m in model_system_user_account: - print("\t - migrate '{}'".format(model.__name__)) - count = 0 - bulk_size = 1000 - - while True: - start = time.time() - objects = model.objects.all().prefetch_related(old_field)[count:bulk_size] - if not objects: - break - count += len(objects) - - updated = [] - for obj in objects: - if m2m: - old_value = getattr(obj, old_field).all() - new_value = [s.username for s in old_value] - else: - old_value = getattr(obj, old_field) - new_value = old_value.username if old_value else '' - setattr(obj, new_field, new_value) - updated.append(obj) - model.objects.bulk_update(updated, [new_field]) - print(" Migrate account: {}-{} using: {:.2f}s".format( - count - len(objects), count, time.time() - start - )) - - -class Migration(migrations.Migration): - dependencies = [ - ('tickets', '0019_delete_applyapplicationticket'), - ] - - operations = [ - migrations.AlterField( - model_name='applyassetticket', - name='apply_permission_name', - field=models.CharField(max_length=128, verbose_name='Permission name'), - ), - migrations.AddField( - model_name='applyassetticket', - name='apply_accounts', - field=models.JSONField(default=list, verbose_name='Apply accounts'), - ), - migrations.AddField( - model_name='applycommandticket', - name='apply_run_account', - field=models.CharField(default='', max_length=128, verbose_name='Run account'), - ), - migrations.AddField( - model_name='applyloginassetticket', - name='apply_login_account', - field=models.CharField(default='', max_length=128, verbose_name='Login account'), - ), - migrations.RunPython(migrate_system_to_account), - migrations.RemoveField( - model_name='applyassetticket', - name='apply_system_users', - ), - migrations.RemoveField( - model_name='applycommandticket', - name='apply_run_system_user', - ), - migrations.RemoveField( - model_name='applyloginassetticket', - name='apply_login_system_user', - ), - ] diff --git a/apps/tickets/migrations/0021_auto_20220921_1814.py b/apps/tickets/migrations/0021_auto_20220921_1814.py deleted file mode 100644 index 5e9db6e06..000000000 --- a/apps/tickets/migrations/0021_auto_20220921_1814.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 3.2.13 on 2022-09-21 10:14 - -from django.db import migrations, models - - -def migrate_remove_application_flow(apps, schema_editor): - flow_model = apps.get_model('tickets', 'TicketFlow') - flow_model.objects.filter(type='apply_application').delete() - - -class Migration(migrations.Migration): - dependencies = [ - ('tickets', '0020_auto_20220817_1346'), - ] - - operations = [ - migrations.AlterField( - model_name='ticket', - name='type', - field=models.CharField( - choices=[('general', 'General'), ('login_confirm', 'Login confirm'), ('apply_asset', 'Apply for asset'), - ('login_asset_confirm', 'Login asset confirm'), ('command_confirm', 'Command confirm')], - default='general', max_length=64, verbose_name='Type'), - ), - migrations.AlterField( - model_name='ticketflow', - name='type', - field=models.CharField( - choices=[('general', 'General'), ('login_confirm', 'Login confirm'), ('apply_asset', 'Apply for asset'), - ('login_asset_confirm', 'Login asset confirm'), ('command_confirm', 'Command confirm')], - default='general', max_length=64, verbose_name='Type'), - ), - migrations.RunPython(migrate_remove_application_flow), - ] diff --git a/apps/tickets/migrations/0022_alter_applyassetticket_apply_actions.py b/apps/tickets/migrations/0022_alter_applyassetticket_apply_actions.py deleted file mode 100644 index 96f645e0d..000000000 --- a/apps/tickets/migrations/0022_alter_applyassetticket_apply_actions.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.14 on 2022-11-11 11:19 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0021_auto_20220921_1814'), - ] - - operations = [ - migrations.AlterField( - model_name='applyassetticket', - name='apply_actions', - field=models.IntegerField(default=1, verbose_name='Actions'), - ), - ] diff --git a/apps/tickets/migrations/0023_alter_applyassetticket_apply_actions.py b/apps/tickets/migrations/0023_alter_applyassetticket_apply_actions.py deleted file mode 100644 index 871628ff9..000000000 --- a/apps/tickets/migrations/0023_alter_applyassetticket_apply_actions.py +++ /dev/null @@ -1,83 +0,0 @@ -# Generated by Django 3.2.14 on 2022-11-18 03:00 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('tickets', '0022_alter_applyassetticket_apply_actions'), - ] - - operations = [ - migrations.AlterField( - model_name='applyassetticket', - name='apply_actions', - field=models.IntegerField(default=1, verbose_name='Actions'), - ), - migrations.AlterField( - model_name='approvalrule', - name='strategy', - field=models.CharField( - choices=[ - ('org_admin', 'Org admin'), ('custom_user', 'Custom user'), - ('super_admin', 'Super admin'), ('super_org_admin', 'Super admin and org admin') - ], default='super_admin', max_length=64, - verbose_name='Approve strategy'), - ), - migrations.AlterField( - model_name='ticket', - name='state', - field=models.CharField( - choices=[ - ('pending', 'Open'), ('closed', 'Cancel'), - ('approved', 'Approved'), ('rejected', 'Rejected') - ], default='pending', max_length=16, verbose_name='State'), - ), - migrations.AlterField( - model_name='ticket', - name='type', - field=models.CharField( - choices=[ - ('general', 'General'), ('apply_asset', 'Apply for asset'), - ('login_confirm', 'Login confirm'), ('command_confirm', 'Command confirm'), - ('login_asset_confirm', 'Login asset confirm') - ], - default='general', max_length=64, verbose_name='Type'), - ), - migrations.AlterField( - model_name='ticketassignee', - name='state', - field=models.CharField( - choices=[ - ('pending', 'Open'), ('closed', 'Cancel'), - ('approved', 'Approved'), ('rejected', 'Rejected') - ], default='pending', max_length=64), - ), - migrations.AlterField( - model_name='ticketflow', - name='type', - field=models.CharField( - choices=[ - ('general', 'General'), ('apply_asset', 'Apply for asset'), - ('login_confirm', 'Login confirm'), ('command_confirm', 'Command confirm'), - ('login_asset_confirm', 'Login asset confirm') - ], - default='general', max_length=64, verbose_name='Type'), - ), - migrations.AlterField( - model_name='ticketstep', - name='state', - field=models.CharField( - choices=[ - ('pending', 'Pending'), ('closed', 'Closed'), - ('approved', 'Approved'), ('rejected', 'Rejected') - ], default='pending', max_length=64, verbose_name='State'), - ), - migrations.AlterField( - model_name='ticketstep', - name='status', - field=models.CharField( - choices=[('active', 'Active'), ('closed', 'Closed'), ('pending', 'Pending')], - default='pending', max_length=16), - ), - ] diff --git a/apps/tickets/migrations/0024_auto_20221121_1800.py b/apps/tickets/migrations/0024_auto_20221121_1800.py deleted file mode 100644 index 92f676615..000000000 --- a/apps/tickets/migrations/0024_auto_20221121_1800.py +++ /dev/null @@ -1,63 +0,0 @@ -# Generated by Django 3.2.14 on 2022-11-21 10:00 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('tickets', '0023_alter_applyassetticket_apply_actions'), - ] - - operations = [ - migrations.AlterField( - model_name='approvalrule', - name='strategy', - field=models.CharField( - choices=[('org_admin', 'Org admin'), ('custom_user', 'Custom user'), ('super_admin', 'Super admin'), - ('super_org_admin', 'Super admin and org admin')], default='super_admin', max_length=64, - verbose_name='Approve strategy'), - ), - migrations.AlterField( - model_name='ticket', - name='state', - field=models.CharField( - choices=[('pending', 'Open'), ('closed', 'Cancel'), ('approved', 'Approved'), ('rejected', 'Rejected')], - default='pending', max_length=16, verbose_name='State'), - ), - migrations.AlterField( - model_name='ticket', - name='type', - field=models.CharField( - choices=[('general', 'General'), ('apply_asset', 'Apply for asset'), ('login_confirm', 'Login confirm'), - ('command_confirm', 'Command confirm'), ('login_asset_confirm', 'Login asset confirm')], - default='general', max_length=64, verbose_name='Type'), - ), - migrations.AlterField( - model_name='ticketassignee', - name='state', - field=models.CharField( - choices=[('pending', 'Open'), ('closed', 'Cancel'), ('approved', 'Approved'), ('rejected', 'Rejected')], - default='pending', max_length=64), - ), - migrations.AlterField( - model_name='ticketflow', - name='type', - field=models.CharField( - choices=[('general', 'General'), ('apply_asset', 'Apply for asset'), ('login_confirm', 'Login confirm'), - ('command_confirm', 'Command confirm'), ('login_asset_confirm', 'Login asset confirm')], - default='general', max_length=64, verbose_name='Type'), - ), - migrations.AlterField( - model_name='ticketstep', - name='state', - field=models.CharField(choices=[('pending', 'Pending'), ('closed', 'Closed'), ('approved', 'Approved'), - ('rejected', 'Rejected')], default='pending', max_length=64, - verbose_name='State'), - ), - migrations.AlterField( - model_name='ticketstep', - name='status', - field=models.CharField(choices=[('active', 'Active'), ('closed', 'Closed'), ('pending', 'Pending')], - default='pending', max_length=16), - ), - ] diff --git a/apps/tickets/migrations/0025_auto_20221206_1820.py b/apps/tickets/migrations/0025_auto_20221206_1820.py deleted file mode 100644 index ca9947158..000000000 --- a/apps/tickets/migrations/0025_auto_20221206_1820.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-06 10:20 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('acls', '0008_commandgroup_comment'), - ('tickets', '0024_auto_20221121_1800'), - ] - - operations = [ - migrations.RemoveField( - model_name='applycommandticket', - name='apply_from_cmd_filter', - ), - migrations.RemoveField( - model_name='applycommandticket', - name='apply_from_cmd_filter_rule', - ), - migrations.AddField( - model_name='applycommandticket', - name='apply_from_cmd_filter_acl', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='acls.commandfilteracl', - verbose_name='Command filter acl'), - ), - ] diff --git a/apps/tickets/migrations/0026_auto_20221220_1956.py b/apps/tickets/migrations/0026_auto_20221220_1956.py deleted file mode 100644 index 67f590f7b..000000000 --- a/apps/tickets/migrations/0026_auto_20221220_1956.py +++ /dev/null @@ -1,98 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0025_auto_20221206_1820'), - ] - - operations = [ - migrations.AddField( - model_name='approvalrule', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='approvalrule', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='comment', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='comment', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='ticket', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='ticketassignee', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='ticketassignee', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='ticketflow', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='ticketflow', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AddField( - model_name='ticketstep', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AddField( - model_name='ticketstep', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='approvalrule', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='comment', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='ticket', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='ticketassignee', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='ticketflow', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - migrations.AlterField( - model_name='ticketstep', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - ] diff --git a/apps/tickets/migrations/0027_alter_applycommandticket_apply_run_account.py b/apps/tickets/migrations/0027_alter_applycommandticket_apply_run_account.py deleted file mode 100644 index b491cbbc0..000000000 --- a/apps/tickets/migrations/0027_alter_applycommandticket_apply_run_account.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.16 on 2022-12-23 07:36 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0026_auto_20221220_1956'), - ] - - operations = [ - migrations.AlterField( - model_name='applycommandticket', - name='apply_run_account', - field=models.CharField(default='', max_length=128, verbose_name='Account'), - ), - ] diff --git a/apps/tickets/migrations/0028_remove_app_tickets.py b/apps/tickets/migrations/0028_remove_app_tickets.py deleted file mode 100644 index b396d6c2a..000000000 --- a/apps/tickets/migrations/0028_remove_app_tickets.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.16 on 2022-12-28 09:46 - -from django.db import migrations - - -def migrate_remove_app_tickets(apps, *args): - model = apps.get_model('tickets', 'Ticket') - model.objects.filter(type='apply_application').delete() - - -class Migration(migrations.Migration): - dependencies = [ - ('tickets', '0027_alter_applycommandticket_apply_run_account'), - ] - - operations = [ - migrations.RunPython(migrate_remove_app_tickets) - ] diff --git a/apps/tickets/migrations/0029_auto_20230110_1445.py b/apps/tickets/migrations/0029_auto_20230110_1445.py deleted file mode 100644 index f17928740..000000000 --- a/apps/tickets/migrations/0029_auto_20230110_1445.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 3.2.16 on 2023-01-10 06:45 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0107_automation'), - ('tickets', '0028_remove_app_tickets'), - ] - - operations = [ - migrations.AlterModelOptions( - name='applyassetticket', - options={'verbose_name': 'Apply Asset Ticket'}, - ), - migrations.AlterField( - model_name='applyassetticket', - name='apply_assets', - field=models.ManyToManyField(to='assets.Asset', verbose_name='Asset'), - ), - migrations.AlterField( - model_name='applyassetticket', - name='apply_nodes', - field=models.ManyToManyField(to='assets.Node', verbose_name='Node'), - ), - ] diff --git a/apps/users/migrations/0001_initial.py b/apps/users/migrations/0001_initial.py index b4205d231..8a4459b0a 100644 --- a/apps/users/migrations/0001_initial.py +++ b/apps/users/migrations/0001_initial.py @@ -1,16 +1,17 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2017-12-21 16:06 -from __future__ import unicode_literals +# Generated by Django 4.1.13 on 2024-05-09 03:16 +import common.db.fields +import common.db.models +from django.contrib.auth.hashers import make_password +import common.utils.django +from django.conf import settings +import django.contrib.auth.models +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import users.models.user import uuid -import django.contrib.auth.models -import django.utils.timezone -from django.conf import settings -from django.contrib.auth.hashers import make_password -from django.db import migrations, models - -import common.utils def add_default_group(apps, schema_editor): @@ -35,10 +36,11 @@ def add_default_admin(apps, schema_editor): class Migration(migrations.Migration): + initial = True dependencies = [ - ('auth', '0008_alter_user_username_max_length'), + ('auth', '0012_alter_user_first_name_max_length'), ] operations = [ @@ -47,104 +49,108 @@ class Migration(migrations.Migration): fields=[ ('password', models.CharField(max_length=128, verbose_name='password')), ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), - ('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')), - ('is_active', models.BooleanField(default=True, - help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', - verbose_name='active')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('username', models.CharField(max_length=20, unique=True, verbose_name='Username')), - ('name', models.CharField(max_length=20, verbose_name='Name')), - ('email', models.EmailField(max_length=30, unique=True, verbose_name='Email')), - ('role', models.CharField(blank=True, choices=[('Admin', 'Administrator'), ('User', 'User'), - ('App', 'Application')], default='User', max_length=10, - verbose_name='Role')), + ('username', models.CharField(max_length=128, unique=True, verbose_name='Username')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('email', models.EmailField(max_length=128, unique=True, verbose_name='Email')), + ('role', models.CharField(blank=True, default='User', max_length=10, verbose_name='Role')), + ('is_service_account', models.BooleanField(default=False, verbose_name='Is service account')), ('avatar', models.ImageField(null=True, upload_to='avatar', verbose_name='Avatar')), - ('wechat', models.CharField(blank=True, max_length=30, verbose_name='Wechat')), - ('phone', models.CharField(blank=True, max_length=20, null=True, verbose_name='Phone')), - ('enable_otp', models.BooleanField(default=False, verbose_name='Enable OTP')), - ('secret_key_otp', models.CharField(blank=True, max_length=16)), - ('_private_key', models.CharField(blank=True, max_length=5000, verbose_name='Private key')), - ('_public_key', models.CharField(blank=True, max_length=5000, verbose_name='Public key')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), - ('is_first_login', models.BooleanField(default=False)), - ('date_expired', models.DateTimeField(blank=True, default=common.utils.date_expired_default, null=True, - verbose_name='Date expired')), - ('created_by', models.CharField(default='', max_length=30, verbose_name='Created by')), + ('wechat', common.db.fields.EncryptCharField(blank=True, max_length=128, verbose_name='Wechat')), + ('phone', common.db.fields.EncryptCharField(blank=True, max_length=128, null=True, verbose_name='Phone')), + ('mfa_level', models.SmallIntegerField(choices=[(0, 'Disable'), (1, 'Enable'), (2, 'Force enable')], default=0, verbose_name='MFA')), + ('otp_secret_key', common.db.fields.EncryptCharField(blank=True, max_length=128, null=True, verbose_name='OTP secret key')), + ('private_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Private key')), + ('public_key', common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Public key')), + ('comment', models.TextField(blank=True, null=True, verbose_name='Comment')), + ('is_first_login', models.BooleanField(default=True, verbose_name='Is first login')), + ('date_expired', models.DateTimeField(blank=True, db_index=True, default=common.utils.django.date_expired_default, null=True, verbose_name='Date expired')), + ('created_by', models.CharField(blank=True, default='', max_length=30, verbose_name='Created by')), + ('updated_by', models.CharField(blank=True, default='', max_length=30, verbose_name='Updated by')), + ('date_password_last_updated', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date password last updated')), + ('need_update_password', models.BooleanField(default=False, verbose_name='Need update password')), + ('source', models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID'), ('radius', 'Radius'), ('cas', 'CAS'), ('saml2', 'SAML2'), ('oauth2', 'OAuth2'), ('wecom', 'WeCom'), ('dingtalk', 'DingTalk'), ('feishu', 'FeiShu'), ('lark', 'Lark'), ('slack', 'Slack'), ('custom', 'Custom')], default='local', max_length=30, verbose_name='Source')), + ('wecom_id', models.CharField(default=None, max_length=128, null=True, verbose_name='WeCom')), + ('dingtalk_id', models.CharField(default=None, max_length=128, null=True, verbose_name='DingTalk')), + ('feishu_id', models.CharField(default=None, max_length=128, null=True, verbose_name='FeiShu')), + ('lark_id', models.CharField(default=None, max_length=128, null=True, verbose_name='Lark')), + ('slack_id', models.CharField(default=None, max_length=128, null=True, verbose_name='Slack')), + ('date_api_key_last_used', models.DateTimeField(blank=True, null=True, verbose_name='Date api key used')), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ], options={ + 'verbose_name': 'User', 'ordering': ['username'], + 'permissions': [('invite_user', 'Can invite user'), ('remove_user', 'Can remove user'), ('match_user', 'Can match user')], }, + bases=(users.models.user.AuthMixin, users.models.user.SourceMixin, users.models.user.TokenMixin, users.models.user.RoleMixin, users.models.user.MFAMixin, users.models.user.JSONFilterMixin, models.Model), managers=[ ('objects', django.contrib.auth.models.UserManager()), ], ), migrations.CreateModel( - name='AccessKey', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, - verbose_name='AccessKeyID')), - ('secret', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='AccessKeySecret')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='access_key', - to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - ), - migrations.CreateModel( - name='LoginLog', + name='UserPasswordHistory', fields=[ ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('username', models.CharField(max_length=20, verbose_name='Username')), - ('type', - models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')], max_length=2, verbose_name='Login type')), - ('ip', models.GenericIPAddressField(verbose_name='Login IP')), - ('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')), - ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Login Date')), + ('password', models.CharField(max_length=128)), + ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), + ('user', models.ForeignKey(on_delete=common.db.models.CASCADE_SIGNAL_SKIP, related_name='history_passwords', to=settings.AUTH_USER_MODEL, verbose_name='User')), ], options={ - 'ordering': ['-datetime', 'username'], - }, - ), - migrations.CreateModel( - name='PrivateToken', - fields=[ - ('key', models.CharField(max_length=40, primary_key=True, serialize=False, verbose_name='Key')), - ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='auth_token', - to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'verbose_name': 'Private Token', + 'verbose_name': 'User password history', }, ), migrations.CreateModel( name='UserGroup', fields=[ - ('is_discard', models.BooleanField(default=False, verbose_name='is discard')), - ('discard_time', models.DateTimeField(blank=True, null=True, verbose_name='discard time')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('comment', models.TextField(blank=True, verbose_name='Comment')), + ('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')), - ('created_by', models.CharField(max_length=100)), + ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), + ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), + ('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')), + ('name', models.CharField(max_length=128, verbose_name='Name')), ], options={ + 'verbose_name': 'User group', 'ordering': ['name'], + 'unique_together': {('org_id', 'name')}, }, ), migrations.AddField( model_name='user', name='groups', - field=models.ManyToManyField(blank=True, related_name='users', to='users.UserGroup', - verbose_name='User group'), + field=models.ManyToManyField(blank=True, related_name='users', to='users.usergroup', verbose_name='User group'), ), migrations.AddField( model_name='user', name='user_permissions', - field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', - related_name='user_set', related_query_name='user', to='auth.Permission', - verbose_name='user permissions'), + field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions'), + ), + migrations.CreateModel( + name='Preference', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('category', models.CharField(max_length=128, verbose_name='Category')), + ('value', models.TextField(blank=True, null=True, verbose_name='Value')), + ('encrypted', models.BooleanField(default=False, verbose_name='Encrypted')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='preferences', to=settings.AUTH_USER_MODEL, verbose_name='Users')), + ], + options={ + 'verbose_name': 'Preference', + 'db_table': 'users_preference', + 'unique_together': {('name', 'user_id')}, + }, + ), + migrations.AlterUniqueTogether( + name='user', + unique_together={('dingtalk_id',), ('feishu_id',), ('wecom_id',), ('lark_id',), ('slack_id',)}, ), migrations.RunPython(add_default_group), migrations.RunPython(add_default_admin), diff --git a/apps/users/migrations/0002_auto_20171225_1157.py b/apps/users/migrations/0002_auto_20171225_1157.py deleted file mode 100644 index 6b5bae73c..000000000 --- a/apps/users/migrations/0002_auto_20171225_1157.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2017-12-25 03:57 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='email', - field=models.EmailField(max_length=128, unique=True, verbose_name='Email'), - ), - migrations.AlterField( - model_name='user', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterField( - model_name='user', - name='username', - field=models.CharField(max_length=128, unique=True, verbose_name='Username'), - ), - migrations.AlterField( - model_name='user', - name='wechat', - field=models.CharField(blank=True, max_length=128, verbose_name='Wechat'), - ), - ] diff --git a/apps/users/migrations/0002_auto_20171225_1157_squashed_0019_auto_20190304_1459.py b/apps/users/migrations/0002_auto_20171225_1157_squashed_0019_auto_20190304_1459.py deleted file mode 100644 index d4bc961ef..000000000 --- a/apps/users/migrations/0002_auto_20171225_1157_squashed_0019_auto_20190304_1459.py +++ /dev/null @@ -1,197 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-02 09:54 - -import common.utils.django -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -# Functions from the following migrations need manual copying. -# Move them and any dependencies into this file, then update the -# RunPython operations to refer to the local versions: -# users.migrations.0010_auto_20180606_1505 - -def remove_deleted_group(apps, schema_editor): - db_alias = schema_editor.connection.alias - group_model = apps.get_model("users", "UserGroup") - group_model.objects.using(db_alias).filter(is_discard=True).delete() - - -class Migration(migrations.Migration): - - replaces = [('users', '0002_auto_20171225_1157'), ('users', '0003_auto_20180101_0046'), ('users', '0004_auto_20180125_1218'), ('users', '0005_auto_20180306_1804'), ('users', '0006_auto_20180411_1135'), ('users', '0007_auto_20180419_1036'), ('users', '0008_auto_20180425_1516'), ('users', '0009_auto_20180517_1537'), ('users', '0010_auto_20180606_1505'), ('users', '0011_user_source'), ('users', '0012_auto_20180710_1641'), ('users', '0013_auto_20180807_1116'), ('users', '0014_auto_20180816_1652'), ('users', '0015_auto_20181105_1112'), ('users', '0016_auto_20181109_1505'), ('users', '0017_auto_20181123_1113'), ('users', '0018_auto_20190107_1912'), ('users', '0019_auto_20190304_1459')] - - dependencies = [ - ('users', '0001_initial'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='email', - field=models.EmailField(max_length=128, unique=True, verbose_name='Email'), - ), - migrations.AlterField( - model_name='user', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterField( - model_name='user', - name='username', - field=models.CharField(max_length=128, unique=True, verbose_name='Username'), - ), - migrations.AlterField( - model_name='user', - name='wechat', - field=models.CharField(blank=True, max_length=128, verbose_name='Wechat'), - ), - migrations.AlterField( - model_name='user', - name='is_first_login', - field=models.BooleanField(default=True, verbose_name='Is first login'), - ), - migrations.AlterField( - model_name='usergroup', - name='created_by', - field=models.CharField(blank=True, max_length=100, null=True), - ), - migrations.AlterModelOptions( - name='user', - options={'ordering': ['username'], 'verbose_name': 'User'}, - ), - migrations.AlterModelOptions( - name='usergroup', - options={'ordering': ['name'], 'verbose_name': 'User group'}, - ), - migrations.RenameField( - model_name='user', - old_name='secret_key_otp', - new_name='otp_secret_key', - ), - migrations.RemoveField( - model_name='user', - name='enable_otp', - ), - migrations.AddField( - model_name='user', - name='otp_level', - field=models.SmallIntegerField(choices=[(0, 'Disable'), (1, 'Enable'), (2, 'Force enable')], default=0, verbose_name='MFA'), - ), - migrations.RemoveField( - model_name='user', - name='otp_secret_key', - ), - migrations.AddField( - model_name='user', - name='_otp_secret_key', - field=models.CharField(blank=True, max_length=128, null=True), - ), - migrations.AlterField( - model_name='usergroup', - name='name', - field=models.CharField(max_length=128, unique=True, verbose_name='Name'), - ), - migrations.RunPython( - code=remove_deleted_group, - ), - migrations.RemoveField( - model_name='usergroup', - name='discard_time', - ), - migrations.RemoveField( - model_name='usergroup', - name='is_discard', - ), - migrations.AlterField( - model_name='user', - name='date_expired', - field=models.DateTimeField(blank=True, db_index=True, default=common.utils.django.date_expired_default, null=True, verbose_name='Date expired'), - ), - migrations.AddField( - model_name='user', - name='source', - field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID'), ('radius', 'Radius')], default='local', max_length=30, verbose_name='Source'), - ), - migrations.AddField( - model_name='loginlog', - name='mfa', - field=models.SmallIntegerField(choices=[(0, 'Disabled'), (1, 'Enabled'), (2, '-')], default=2, verbose_name='MFA'), - ), - migrations.AddField( - model_name='loginlog', - name='reason', - field=models.SmallIntegerField(choices=[(0, '-'), (1, 'Username/password check failed'), (2, 'MFA authentication failed'), (3, 'Username does not exist'), (4, 'Password expired')], default=0, verbose_name='Reason'), - ), - migrations.AddField( - model_name='loginlog', - name='status', - field=models.BooleanField(choices=[(True, 'Success'), (False, 'Failed')], default=True, max_length=2, verbose_name='Status'), - ), - migrations.AddField( - model_name='usergroup', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AlterField( - model_name='user', - name='last_name', - field=models.CharField(blank=True, max_length=150, verbose_name='last name'), - ), - migrations.AlterField( - model_name='usergroup', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='usergroup', - unique_together={('org_id', 'name')}, - ), - migrations.AlterField( - model_name='usergroup', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - migrations.AlterField( - model_name='loginlog', - name='username', - field=models.CharField(max_length=128, verbose_name='Username'), - ), - migrations.AddField( - model_name='user', - name='date_password_last_updated', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date password last updated'), - ), - migrations.AlterField( - model_name='accesskey', - name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='access_keys', to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - migrations.SeparateDatabaseAndState( - database_operations=[ - migrations.AlterModelTable( - name='accesskey', - table='authentication_accesskey', - ), - migrations.AlterModelTable( - name='privatetoken', - table='authentication_privatetoken', - ), - migrations.AlterModelTable( - name='loginlog', - table='audits_userloginlog', - ), - ], - state_operations=[ - migrations.DeleteModel( - name='accesskey', - ), - migrations.DeleteModel( - name='privatetoken', - ), - migrations.DeleteModel( - name='loginlog', - ), - ], - ), - ] diff --git a/apps/users/migrations/0003_auto_20180101_0046.py b/apps/users/migrations/0003_auto_20180101_0046.py deleted file mode 100644 index 6795a1782..000000000 --- a/apps/users/migrations/0003_auto_20180101_0046.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2017-12-31 16:46 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0002_auto_20171225_1157'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='is_first_login', - field=models.BooleanField(default=True, verbose_name='Is first login'), - ), - ] diff --git a/apps/users/migrations/0004_auto_20180125_1218.py b/apps/users/migrations/0004_auto_20180125_1218.py deleted file mode 100644 index b97f8f6c4..000000000 --- a/apps/users/migrations/0004_auto_20180125_1218.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-25 04:18 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0003_auto_20180101_0046'), - ] - - operations = [ - migrations.AlterField( - model_name='usergroup', - name='created_by', - field=models.CharField(blank=True, max_length=100, null=True), - ), - ] diff --git a/apps/users/migrations/0005_auto_20180306_1804.py b/apps/users/migrations/0005_auto_20180306_1804.py deleted file mode 100644 index 417d6b021..000000000 --- a/apps/users/migrations/0005_auto_20180306_1804.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-03-06 10:04 -from __future__ import unicode_literals - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0004_auto_20180125_1218'), - ] - - operations = [ - migrations.AlterModelOptions( - name='user', - options={'ordering': ['username'], 'verbose_name': 'User'}, - ), - migrations.AlterModelOptions( - name='usergroup', - options={'ordering': ['name'], 'verbose_name': 'User group'}, - ), - ] diff --git a/apps/users/migrations/0006_auto_20180411_1135.py b/apps/users/migrations/0006_auto_20180411_1135.py deleted file mode 100644 index 04844f630..000000000 --- a/apps/users/migrations/0006_auto_20180411_1135.py +++ /dev/null @@ -1,29 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-11 03:35 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0005_auto_20180306_1804'), - ] - - operations = [ - migrations.RenameField( - model_name='user', - old_name='secret_key_otp', - new_name='otp_secret_key', - ), - migrations.RemoveField( - model_name='user', - name='enable_otp', - ), - migrations.AddField( - model_name='user', - name='otp_level', - field=models.SmallIntegerField(choices=[(0, 'Disable'), (1, 'Enable'), (2, 'Force enable')], default=0, verbose_name='Enable OTP'), - ), - ] diff --git a/apps/users/migrations/0007_auto_20180419_1036.py b/apps/users/migrations/0007_auto_20180419_1036.py deleted file mode 100644 index 3357cc2a5..000000000 --- a/apps/users/migrations/0007_auto_20180419_1036.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-19 02:36 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0006_auto_20180411_1135'), - ] - - operations = [ - migrations.RemoveField( - model_name='user', - name='otp_secret_key', - ), - migrations.AddField( - model_name='user', - name='_otp_secret_key', - field=models.CharField(blank=True, max_length=128, null=True), - ), - ] diff --git a/apps/users/migrations/0008_auto_20180425_1516.py b/apps/users/migrations/0008_auto_20180425_1516.py deleted file mode 100644 index 43bd38c07..000000000 --- a/apps/users/migrations/0008_auto_20180425_1516.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-04-25 07:16 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0007_auto_20180419_1036'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='otp_level', - field=models.SmallIntegerField(choices=[(0, 'Disable'), (1, 'Enable'), (2, 'Force enable')], default=0, verbose_name='MFA'), - ), - ] diff --git a/apps/users/migrations/0009_auto_20180517_1537.py b/apps/users/migrations/0009_auto_20180517_1537.py deleted file mode 100644 index 7938648f5..000000000 --- a/apps/users/migrations/0009_auto_20180517_1537.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-05-17 07:37 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0008_auto_20180425_1516'), - ] - - operations = [ - migrations.AlterField( - model_name='usergroup', - name='name', - field=models.CharField(max_length=128, unique=True, verbose_name='Name'), - ), - ] diff --git a/apps/users/migrations/0010_auto_20180606_1505.py b/apps/users/migrations/0010_auto_20180606_1505.py deleted file mode 100644 index bf8eea430..000000000 --- a/apps/users/migrations/0010_auto_20180606_1505.py +++ /dev/null @@ -1,38 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-06-06 07:05 -from __future__ import unicode_literals - -import common.utils -from django.db import migrations, models - - -def remove_deleted_group(apps, schema_editor): - db_alias = schema_editor.connection.alias - group_model = apps.get_model("users", "UserGroup") - group_model.objects.using(db_alias).filter(is_discard=True).delete() - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0009_auto_20180517_1537'), - ] - - operations = [ - migrations.RunPython( - remove_deleted_group - ), - migrations.RemoveField( - model_name='usergroup', - name='discard_time', - ), - migrations.RemoveField( - model_name='usergroup', - name='is_discard', - ), - migrations.AlterField( - model_name='user', - name='date_expired', - field=models.DateTimeField(blank=True, db_index=True, default=common.utils.date_expired_default, null=True, verbose_name='Date expired'), - ), - ] diff --git a/apps/users/migrations/0011_user_source.py b/apps/users/migrations/0011_user_source.py deleted file mode 100644 index 584036cfc..000000000 --- a/apps/users/migrations/0011_user_source.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-06-07 04:58 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0010_auto_20180606_1505'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='source', - field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD')], default='local', max_length=30, verbose_name='Source'), - ), - ] diff --git a/apps/users/migrations/0012_auto_20180710_1641.py b/apps/users/migrations/0012_auto_20180710_1641.py deleted file mode 100644 index ad6628941..000000000 --- a/apps/users/migrations/0012_auto_20180710_1641.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.13 on 2018-07-10 08:41 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0011_user_source'), - ] - - operations = [ - migrations.AddField( - model_name='loginlog', - name='mfa', - field=models.SmallIntegerField(choices=[(0, 'Disabled'), (1, 'Enabled'), (2, '-')], default=2, verbose_name='MFA'), - ), - migrations.AddField( - model_name='loginlog', - name='reason', - field=models.SmallIntegerField(choices=[(0, '-'), (1, 'Username/password check failed'), (2, 'MFA authentication failed')], default=0, verbose_name='Reason'), - ), - migrations.AddField( - model_name='loginlog', - name='status', - field=models.BooleanField(choices=[(True, 'Success'), (False, 'Failed')], default=True, max_length=2, verbose_name='Status'), - ), - ] diff --git a/apps/users/migrations/0013_auto_20180807_1116.py b/apps/users/migrations/0013_auto_20180807_1116.py deleted file mode 100644 index 2b56bc42b..000000000 --- a/apps/users/migrations/0013_auto_20180807_1116.py +++ /dev/null @@ -1,32 +0,0 @@ -# Generated by Django 2.0.7 on 2018-08-07 03:16 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0012_auto_20180710_1641'), - ] - - operations = [ - migrations.AddField( - model_name='usergroup', - name='org_id', - field=models.CharField(blank=True, default=None, max_length=36, null=True), - ), - migrations.AlterField( - model_name='user', - name='last_name', - field=models.CharField(blank=True, max_length=150, verbose_name='last name'), - ), - migrations.AlterField( - model_name='usergroup', - name='name', - field=models.CharField(max_length=128, verbose_name='Name'), - ), - migrations.AlterUniqueTogether( - name='usergroup', - unique_together={('org_id', 'name')}, - ), - ] diff --git a/apps/users/migrations/0014_auto_20180816_1652.py b/apps/users/migrations/0014_auto_20180816_1652.py deleted file mode 100644 index 0be502ec3..000000000 --- a/apps/users/migrations/0014_auto_20180816_1652.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.0.7 on 2018-08-16 08:52 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0013_auto_20180807_1116'), - ] - - operations = [ - migrations.AlterField( - model_name='usergroup', - name='org_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization'), - ), - ] diff --git a/apps/users/migrations/0015_auto_20181105_1112.py b/apps/users/migrations/0015_auto_20181105_1112.py deleted file mode 100644 index b84e9fa97..000000000 --- a/apps/users/migrations/0015_auto_20181105_1112.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 2.1.1 on 2018-11-05 03:12 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0014_auto_20180816_1652'), - ] - - operations = [ - migrations.AlterField( - model_name='loginlog', - name='reason', - field=models.SmallIntegerField(choices=[(0, '-'), (1, 'Username/password check failed'), (2, 'MFA authentication failed'), (3, 'Username does not exist')], default=0, verbose_name='Reason'), - ), - migrations.AlterField( - model_name='loginlog', - name='username', - field=models.CharField(max_length=128, verbose_name='Username'), - ), - ] diff --git a/apps/users/migrations/0016_auto_20181109_1505.py b/apps/users/migrations/0016_auto_20181109_1505.py deleted file mode 100644 index c1b8c3bf6..000000000 --- a/apps/users/migrations/0016_auto_20181109_1505.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.1 on 2018-11-09 07:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0015_auto_20181105_1112'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='source', - field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID')], default='local', max_length=30, verbose_name='Source'), - ), - ] diff --git a/apps/users/migrations/0017_auto_20181123_1113.py b/apps/users/migrations/0017_auto_20181123_1113.py deleted file mode 100644 index f9a4f7c97..000000000 --- a/apps/users/migrations/0017_auto_20181123_1113.py +++ /dev/null @@ -1,30 +0,0 @@ -# Generated by Django 2.1.1 on 2018-11-23 03:13 - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0016_auto_20181109_1505'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='date_password_last_updated', - field=models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date password last updated'), - ), - migrations.AlterField( - model_name='accesskey', - name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='access_keys', to=settings.AUTH_USER_MODEL, verbose_name='User'), - ), - migrations.AlterField( - model_name='loginlog', - name='reason', - field=models.SmallIntegerField(choices=[(0, '-'), (1, 'Username/password check failed'), (2, 'MFA authentication failed'), (3, 'Username does not exist'), (4, 'Password expired')], default=0, verbose_name='Reason'), - ), - ] diff --git a/apps/users/migrations/0018_auto_20190107_1912.py b/apps/users/migrations/0018_auto_20190107_1912.py deleted file mode 100644 index 244de970d..000000000 --- a/apps/users/migrations/0018_auto_20190107_1912.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.4 on 2019-01-07 11:12 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0017_auto_20181123_1113'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='source', - field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID'), ('radius', 'Radius')], default='local', max_length=30, verbose_name='Source'), - ), - ] diff --git a/apps/users/migrations/0019_auto_20190304_1459.py b/apps/users/migrations/0019_auto_20190304_1459.py deleted file mode 100644 index e8b1ea8d5..000000000 --- a/apps/users/migrations/0019_auto_20190304_1459.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.1.7 on 2019-03-04 06:59 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0018_auto_20190107_1912'), - ] - - database_operations = [ - migrations.AlterModelTable(name='accesskey', table='authentication_accesskey'), - migrations.AlterModelTable(name='privatetoken', table='authentication_privatetoken'), - migrations.AlterModelTable(name='loginlog', table='audits_userloginlog'), - ] - - state_operations = [ - migrations.DeleteModel('accesskey'), - migrations.DeleteModel('privatetoken'), - migrations.DeleteModel('loginlog'), - ] - - operations = [ - migrations.SeparateDatabaseAndState( - database_operations=database_operations, - state_operations=state_operations) - ] diff --git a/apps/users/migrations/0020_auto_20190612_1825.py b/apps/users/migrations/0020_auto_20190612_1825.py deleted file mode 100644 index 7c3a4ae18..000000000 --- a/apps/users/migrations/0020_auto_20190612_1825.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-12 10:25 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0019_auto_20190304_1459'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='role', - field=models.CharField(blank=True, choices=[('Admin', 'Administrator'), ('User', 'User'), ('App', 'Application'), ('Auditor', 'Auditor')], default='User', max_length=10, verbose_name='Role'), - ), - ] diff --git a/apps/users/migrations/0021_auto_20190625_1104.py b/apps/users/migrations/0021_auto_20190625_1104.py deleted file mode 100644 index f2575b933..000000000 --- a/apps/users/migrations/0021_auto_20190625_1104.py +++ /dev/null @@ -1,34 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-25 03:04 - -import common.db.fields -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0020_auto_20190612_1825'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='_otp_secret_key', - field=common.db.fields.EncryptCharField(blank=True, max_length=128, null=True, verbose_name='OTP secret key'), - ), - migrations.AlterField( - model_name='user', - name='_private_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Private key'), - ), - migrations.AlterField( - model_name='user', - name='_public_key', - field=common.db.fields.EncryptTextField(blank=True, null=True, verbose_name='Public key'), - ), - migrations.AlterField( - model_name='user', - name='comment', - field=models.TextField(blank=True, null=True, verbose_name='Comment'), - ), - ] diff --git a/apps/users/migrations/0022_auto_20190625_1105.py b/apps/users/migrations/0022_auto_20190625_1105.py deleted file mode 100644 index 1735e8376..000000000 --- a/apps/users/migrations/0022_auto_20190625_1105.py +++ /dev/null @@ -1,28 +0,0 @@ -# Generated by Django 2.1.7 on 2019-06-25 03:05 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0021_auto_20190625_1104'), - ] - - operations = [ - migrations.RenameField( - model_name='user', - old_name='_otp_secret_key', - new_name='otp_secret_key', - ), - migrations.RenameField( - model_name='user', - old_name='_private_key', - new_name='private_key', - ), - migrations.RenameField( - model_name='user', - old_name='_public_key', - new_name='public_key', - ), - ] diff --git a/apps/users/migrations/0023_auto_20190724_1525.py b/apps/users/migrations/0023_auto_20190724_1525.py deleted file mode 100644 index 3a949a0de..000000000 --- a/apps/users/migrations/0023_auto_20190724_1525.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.1.7 on 2019-07-24 07:25 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0022_auto_20190625_1105'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='created_by', - field=models.CharField(blank=True, default='', max_length=30, verbose_name='Created by'), - ), - ] diff --git a/apps/users/migrations/0024_auto_20191118_1612.py b/apps/users/migrations/0024_auto_20191118_1612.py deleted file mode 100644 index eb368be2f..000000000 --- a/apps/users/migrations/0024_auto_20191118_1612.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.5 on 2019-11-18 08:12 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0023_auto_20190724_1525'), - ] - - operations = [ - migrations.RenameField( - model_name='user', - old_name='otp_level', - new_name='mfa_level', - ), - ] diff --git a/apps/users/migrations/0025_auto_20200206_1216.py b/apps/users/migrations/0025_auto_20200206_1216.py deleted file mode 100644 index 7eed2ad54..000000000 --- a/apps/users/migrations/0025_auto_20200206_1216.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-02-06 04:16 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0024_auto_20191118_1612'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='source', - field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID'), ('radius', 'Radius'), ('cas', 'CAS')], default='local', max_length=30, verbose_name='Source'), - ), - ] diff --git a/apps/users/migrations/0026_auto_20200508_2105.py b/apps/users/migrations/0026_auto_20200508_2105.py deleted file mode 100644 index 0ccd09e09..000000000 --- a/apps/users/migrations/0026_auto_20200508_2105.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-05-08 13:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0025_auto_20200206_1216'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='source', - field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID'), ('radius', 'Radius'), ('cas', 'CAS')], default='ldap', max_length=30, verbose_name='Source'), - ), - ] diff --git a/apps/users/migrations/0027_auto_20200616_1503.py b/apps/users/migrations/0027_auto_20200616_1503.py deleted file mode 100644 index 2a7fb014e..000000000 --- a/apps/users/migrations/0027_auto_20200616_1503.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-06-16 07:03 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0026_auto_20200508_2105'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='source', - field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID'), ('radius', 'Radius'), ('cas', 'CAS')], default='local', max_length=30, verbose_name='Source'), - ), - ] diff --git a/apps/users/migrations/0028_auto_20200728_1805.py b/apps/users/migrations/0028_auto_20200728_1805.py deleted file mode 100644 index 6e57d04a6..000000000 --- a/apps/users/migrations/0028_auto_20200728_1805.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.10 on 2020-07-28 10:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0027_auto_20200616_1503'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='role', - field=models.CharField(blank=True, choices=[('Admin', 'Super administrator'), ('User', 'User'), ('Auditor', 'Super auditor'), ('App', 'Application')], default='User', max_length=10, verbose_name='Role'), - ), - ] diff --git a/apps/users/migrations/0029_auto_20200814_1650.py b/apps/users/migrations/0029_auto_20200814_1650.py deleted file mode 100644 index c6cf3517b..000000000 --- a/apps/users/migrations/0029_auto_20200814_1650.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-14 08:50 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0028_auto_20200728_1805'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='role', - field=models.CharField(blank=True, choices=[('Admin', 'System administrator'), ('User', 'User'), ('Auditor', 'System auditor'), ('App', 'Application')], default='User', max_length=10, verbose_name='Role'), - ), - ] diff --git a/apps/users/migrations/0030_auto_20200819_2041.py b/apps/users/migrations/0030_auto_20200819_2041.py deleted file mode 100644 index 775d38ac5..000000000 --- a/apps/users/migrations/0030_auto_20200819_2041.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 2.2.13 on 2020-08-19 12:41 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0029_auto_20200814_1650'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='role', - field=models.CharField(blank=True, choices=[('Admin', 'System administrator'), ('Auditor', 'System auditor'), ('User', 'User'), ('App', 'Application')], default='User', max_length=10, verbose_name='Role'), - ), - ] diff --git a/apps/users/migrations/0031_auto_20201118_1801.py b/apps/users/migrations/0031_auto_20201118_1801.py deleted file mode 100644 index 6c0f22303..000000000 --- a/apps/users/migrations/0031_auto_20201118_1801.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2020-11-18 10:01 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0030_auto_20200819_2041'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='first_name', - field=models.CharField(blank=True, max_length=150, verbose_name='first name'), - ), - ] diff --git a/apps/users/migrations/0032_userpasswordhistory.py b/apps/users/migrations/0032_userpasswordhistory.py deleted file mode 100644 index 5088b7968..000000000 --- a/apps/users/migrations/0032_userpasswordhistory.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 3.1 on 2021-04-27 12:43 - -import common.db.models -from django.conf import settings -from django.db import migrations, models -import uuid - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0031_auto_20201118_1801'), - ] - - operations = [ - migrations.CreateModel( - name='UserPasswordHistory', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('password', models.CharField(max_length=128)), - ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), - ('user', models.ForeignKey(on_delete=common.db.models.CASCADE_SIGNAL_SKIP, related_name='history_passwords', to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - ), - ] diff --git a/apps/users/migrations/0033_user_need_update_password.py b/apps/users/migrations/0033_user_need_update_password.py deleted file mode 100644 index 8cc1740a9..000000000 --- a/apps/users/migrations/0033_user_need_update_password.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2021-04-28 11:00 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0032_userpasswordhistory'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='need_update_password', - field=models.BooleanField(default=False), - ), - ] diff --git a/apps/users/migrations/0034_auto_20210506_1448.py b/apps/users/migrations/0034_auto_20210506_1448.py deleted file mode 100644 index 449f0ff6e..000000000 --- a/apps/users/migrations/0034_auto_20210506_1448.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 3.1 on 2021-05-06 06:48 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0033_user_need_update_password'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='dingtalk_id', - field=models.CharField(default=None, max_length=128, null=True, verbose_name='DingTalk'), - ), - migrations.AddField( - model_name='user', - name='wecom_id', - field=models.CharField(default=None, max_length=128, null=True, verbose_name='WeCom'), - ), - ] diff --git a/apps/users/migrations/0035_auto_20210526_1100.py b/apps/users/migrations/0035_auto_20210526_1100.py deleted file mode 100644 index 4d4357a2b..000000000 --- a/apps/users/migrations/0035_auto_20210526_1100.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1 on 2021-05-26 03:00 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0034_auto_20210506_1448'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='need_update_password', - field=models.BooleanField(default=False, verbose_name='Need update password'), - ), - ] diff --git a/apps/users/migrations/0036_user_feishu_id.py b/apps/users/migrations/0036_user_feishu_id.py deleted file mode 100644 index 83c8c0d17..000000000 --- a/apps/users/migrations/0036_user_feishu_id.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 3.1.6 on 2021-08-06 02:32 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0035_auto_20210526_1100'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='feishu_id', - field=models.CharField(default=None, max_length=128, null=True, verbose_name='FeiShu'), - ), - migrations.AlterUniqueTogether( - name='user', - unique_together={('feishu_id',), ('wecom_id',), ('dingtalk_id',)}, - ), - ] diff --git a/apps/users/migrations/0037_user_secret_key.py b/apps/users/migrations/0037_user_secret_key.py deleted file mode 100644 index ccd79c70d..000000000 --- a/apps/users/migrations/0037_user_secret_key.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-07 08:23 - -import common.db.fields -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0036_user_feishu_id'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='secret_key', - field=common.db.fields.EncryptCharField(blank=True, max_length=256, null=True, verbose_name='Secret key'), - ), - ] diff --git a/apps/users/migrations/0038_auto_20211209_1140.py b/apps/users/migrations/0038_auto_20211209_1140.py deleted file mode 100644 index 231ac4a48..000000000 --- a/apps/users/migrations/0038_auto_20211209_1140.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-09 03:40 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0037_user_secret_key'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='source', - field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID'), ('radius', 'Radius'), ('cas', 'CAS'), ('saml2', 'SAML2')], default='local', max_length=30, verbose_name='Source'), - ), - ] diff --git a/apps/users/migrations/0039_auto_20211229_1852.py b/apps/users/migrations/0039_auto_20211229_1852.py deleted file mode 100644 index f83b76144..000000000 --- a/apps/users/migrations/0039_auto_20211229_1852.py +++ /dev/null @@ -1,42 +0,0 @@ -# Generated by Django 3.1.13 on 2021-12-29 10:52 - -from django.db import migrations, models - - -def migrate_app_users(apps, schema_editor): - user_model = apps.get_model('users', 'User') - app_users = user_model.objects.filter(role='App') - app_users.update(is_service_account=True) - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0038_auto_20211209_1140'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='is_service_account', - field=models.BooleanField(default=False, verbose_name='Is service account'), - ), - migrations.RunPython(migrate_app_users), - migrations.AlterModelOptions( - name='user', - options={'ordering': ['username'], 'permissions': [('invite', 'Can invite user'), ('remove', 'Can remove user')], 'verbose_name': 'User'}, - ), - migrations.AlterModelOptions( - name='userpasswordhistory', - options={'verbose_name': 'User password history'}, - ), - migrations.AlterField( - model_name='user', - name='role', - field=models.CharField(blank=True, default='User', max_length=10, verbose_name='Role'), - ), - migrations.AlterModelOptions( - name='user', - options={'ordering': ['username'], 'permissions': [('invite_user', 'Can invite user'), ('remove_user', 'Can remove user'), ('match_user', 'Can match user')], 'verbose_name': 'User'}, - ), - ] diff --git a/apps/users/migrations/0040_alter_user_source.py b/apps/users/migrations/0040_alter_user_source.py deleted file mode 100644 index cb90c4971..000000000 --- a/apps/users/migrations/0040_alter_user_source.py +++ /dev/null @@ -1,18 +0,0 @@ - -# Generated by Django 3.2.13 on 2022-08-24 02:57 -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0039_auto_20211229_1852'), - ] - - operations = [ - migrations.AlterField( - model_name='user', - name='source', - field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID'), ('radius', 'Radius'), ('cas', 'CAS'), ('saml2', 'SAML2'), ('oauth2', 'OAuth2'), ('wecom', 'WeCom'), ('dingtalk', 'DingTalk'), ('feishu', 'FeiShu'), ('custom', 'Custom')], default='local', max_length=30, verbose_name='Source'), - ), - ] diff --git a/apps/users/migrations/0041_auto_20221220_1956.py b/apps/users/migrations/0041_auto_20221220_1956.py deleted file mode 100644 index 9ce1be2fe..000000000 --- a/apps/users/migrations/0041_auto_20221220_1956.py +++ /dev/null @@ -1,33 +0,0 @@ -# Generated by Django 3.2.14 on 2022-12-20 11:56 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0040_alter_user_source'), - ] - - operations = [ - migrations.AddField( - model_name='usergroup', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='usergroup', - name='updated_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Updated by'), - ), - migrations.AlterField( - model_name='usergroup', - name='comment', - field=models.TextField(blank=True, default='', verbose_name='Comment'), - ), - migrations.AlterField( - model_name='usergroup', - name='created_by', - field=models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by'), - ), - ] diff --git a/apps/users/migrations/0042_auto_20230203_1201.py b/apps/users/migrations/0042_auto_20230203_1201.py deleted file mode 100644 index d434ea12d..000000000 --- a/apps/users/migrations/0042_auto_20230203_1201.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 3.2.14 on 2023-02-03 04:01 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0041_auto_20221220_1956'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='date_updated', - field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), - ), - migrations.AddField( - model_name='user', - name='updated_by', - field=models.CharField(blank=True, default='', max_length=30, verbose_name='Updated by'), - ), - ] diff --git a/apps/users/migrations/0043_remove_user_secret_key_preference.py b/apps/users/migrations/0043_remove_user_secret_key_preference.py deleted file mode 100644 index a97044b66..000000000 --- a/apps/users/migrations/0043_remove_user_secret_key_preference.py +++ /dev/null @@ -1,77 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-09 14:16 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - -from common.db.utils import Encryptor - - -def migrate_secret_key(apps, *args): - user_model = apps.get_model('users', 'User') - preference_model = apps.get_model('users', 'Preference') - data = user_model.objects.filter( - secret_key__isnull=False - ).values_list('id', 'secret_key') - objs = [] - for user_id, secret_key in data: - secret_key = Encryptor(secret_key).encrypt() - objs.append( - preference_model( - name='secret_key', category='lina', - value=secret_key, encrypted=True, user_id=user_id - ) - ) - preference_model.objects.bulk_create(objs) - - -def migrate_graphical_resolution(apps, *args): - user_model = apps.get_model('users', 'User') - setting_model = apps.get_model('settings', 'Setting') - preference_model = apps.get_model('users', 'Preference') - s = setting_model.objects.filter(name='TERMINAL_GRAPHICAL_RESOLUTION').first() - if (s and s.value == 'Auto') or not s: - return - - value = s.value - objs = [] - for _id in user_model.objects.values_list('id', flat=True): - objs.append( - preference_model( - name='rdp_resolution', category='luna', - value=value, user_id=_id - ) - ) - preference_model.objects.bulk_create(objs) - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0042_auto_20230203_1201'), - ] - - operations = [ - migrations.CreateModel( - name='Preference', - fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=128, verbose_name='Name')), - ('category', models.CharField(max_length=128, verbose_name='Category')), - ('value', models.TextField(blank=True, null=True, verbose_name='Value')), - ('encrypted', models.BooleanField(default=False, verbose_name='Encrypted')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='preferences', - to=settings.AUTH_USER_MODEL, verbose_name='Users')), - ], - options={ - 'verbose_name': 'Preference', - 'db_table': 'users_preference', - 'unique_together': {('name', 'user_id')}, - }, - ), - migrations.RunPython(migrate_secret_key), - migrations.RunPython(migrate_graphical_resolution), - migrations.RemoveField( - model_name='user', - name='secret_key', - ), - ] diff --git a/apps/users/migrations/0044_usersession.py b/apps/users/migrations/0044_usersession.py deleted file mode 100644 index 328965f12..000000000 --- a/apps/users/migrations/0044_usersession.py +++ /dev/null @@ -1,39 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-14 07:23 - -import uuid - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0043_remove_user_secret_key_preference'), - ] - - operations = [ - migrations.CreateModel( - name='UserSession', - fields=[ - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('ip', models.GenericIPAddressField(verbose_name='Login IP')), - ('key', models.CharField(max_length=128, verbose_name='Session key')), - ('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')), - ('type', models.CharField(choices=[('W', 'Web'), ('T', 'Terminal'), ('U', 'Unknown')], max_length=2, - verbose_name='Login type')), - ('backend', models.CharField(default='', max_length=32, verbose_name='Auth backend')), - ('date_created', models.DateTimeField(blank=True, null=True, verbose_name='Date created')), - ('date_expired', - models.DateTimeField(blank=True, db_index=True, null=True, verbose_name='Date expired')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sessions', - to=settings.AUTH_USER_MODEL, verbose_name='User')), - ], - options={ - 'verbose_name': 'User session', - 'ordering': ['-date_created'], - 'permissions': [('offline_usersession', 'Offline user session')], - }, - ), - ] diff --git a/apps/users/migrations/0045_delete_usersession.py b/apps/users/migrations/0045_delete_usersession.py deleted file mode 100644 index 226637adc..000000000 --- a/apps/users/migrations/0045_delete_usersession.py +++ /dev/null @@ -1,16 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-15 08:58 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0044_usersession'), - ] - - operations = [ - migrations.DeleteModel( - name='UserSession', - ), - ] diff --git a/apps/users/migrations/0046_auto_20230927_1456.py b/apps/users/migrations/0046_auto_20230927_1456.py deleted file mode 100644 index d32569026..000000000 --- a/apps/users/migrations/0046_auto_20230927_1456.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.1.10 on 2023-09-27 06:56 - -from django.db import migrations - - -def migrate_user_default_email(apps, *args): - user_cls = apps.get_model('users', 'User') - user_cls.objects\ - .filter(email='admin@mycomany.com')\ - .update(email='admin@example.com') - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0045_delete_usersession'), - ] - - operations = [ - migrations.RunPython(migrate_user_default_email), - ] diff --git a/apps/users/migrations/0047_user_date_api_key_last_used.py b/apps/users/migrations/0047_user_date_api_key_last_used.py deleted file mode 100644 index 21ccd13cb..000000000 --- a/apps/users/migrations/0047_user_date_api_key_last_used.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-08 04:04 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0046_auto_20230927_1456'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='date_api_key_last_used', - field=models.DateTimeField(blank=True, null=True, verbose_name='Date api key used'), - ), - ] diff --git a/apps/users/migrations/0048_wechat_phone_encrypt.py b/apps/users/migrations/0048_wechat_phone_encrypt.py deleted file mode 100644 index 7db87e09e..000000000 --- a/apps/users/migrations/0048_wechat_phone_encrypt.py +++ /dev/null @@ -1,45 +0,0 @@ -# Generated by Django 4.1.10 on 2023-10-10 06:57 - -from django.db import migrations - -import common.db.fields - -users_bulked = [] - - -def get_encrypt_fields_value(apps, *args): - global users_bulked - user_model = apps.get_model('users', 'User') - bulk_size = 2000 - users = user_model.objects.all() - users_bulked = [ - users[i:i + bulk_size] - for i in range(0, users.count(), bulk_size) - ] - - -def migrate_encrypt_fields(apps, *args): - user_model = apps.get_model('users', 'User') - for _users in users_bulked: - user_model.objects.bulk_update(_users, ['phone', 'wechat']) - - -class Migration(migrations.Migration): - dependencies = [ - ('users', '0047_user_date_api_key_last_used'), - ] - - operations = [ - migrations.RunPython(get_encrypt_fields_value), - migrations.AlterField( - model_name='user', - name='wechat', - field=common.db.fields.EncryptCharField(blank=True, max_length=128, verbose_name='Wechat'), - ), - migrations.AlterField( - model_name='user', - name='phone', - field=common.db.fields.EncryptCharField(blank=True, max_length=128, null=True, verbose_name='Phone'), - ), - migrations.RunPython(migrate_encrypt_fields), - ] diff --git a/apps/users/migrations/0049_alter_user_unique_together_user_slack_id_and_more.py b/apps/users/migrations/0049_alter_user_unique_together_user_slack_id_and_more.py deleted file mode 100644 index 5847af8c2..000000000 --- a/apps/users/migrations/0049_alter_user_unique_together_user_slack_id_and_more.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 4.1.10 on 2023-11-23 08:30 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0048_wechat_phone_encrypt'), - ] - - operations = [ - migrations.AlterUniqueTogether( - name='user', - unique_together={('feishu_id',), ('dingtalk_id',), ('wecom_id',)}, - ), - migrations.AddField( - model_name='user', - name='slack_id', - field=models.CharField(default=None, max_length=128, null=True, verbose_name='Slack'), - ), - migrations.AlterField( - model_name='user', - name='source', - field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID'), ('radius', 'Radius'), ('cas', 'CAS'), ('saml2', 'SAML2'), ('oauth2', 'OAuth2'), ('wecom', 'WeCom'), ('dingtalk', 'DingTalk'), ('feishu', 'FeiShu'), ('slack', 'Slack'), ('custom', 'Custom')], default='local', max_length=30, verbose_name='Source'), - ), - migrations.AlterUniqueTogether( - name='user', - unique_together={('slack_id',), ('feishu_id',), ('dingtalk_id',), ('wecom_id',)}, - ), - ] diff --git a/apps/users/migrations/0050_user_lark_id_alter_user_source.py b/apps/users/migrations/0050_user_lark_id_alter_user_source.py deleted file mode 100644 index 762b8ed7e..000000000 --- a/apps/users/migrations/0050_user_lark_id_alter_user_source.py +++ /dev/null @@ -1,27 +0,0 @@ -# Generated by Django 4.1.13 on 2024-03-25 08:55 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('users', '0049_alter_user_unique_together_user_slack_id_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='user', - name='lark_id', - field=models.CharField(default=None, max_length=128, null=True, verbose_name='Lark'), - ), - migrations.AlterField( - model_name='user', - name='source', - field=models.CharField(choices=[('local', 'Local'), ('ldap', 'LDAP/AD'), ('openid', 'OpenID'), ('radius', 'Radius'), ('cas', 'CAS'), ('saml2', 'SAML2'), ('oauth2', 'OAuth2'), ('wecom', 'WeCom'), ('dingtalk', 'DingTalk'), ('feishu', 'FeiShu'), ('lark', 'Lark'), ('slack', 'Slack'), ('custom', 'Custom')], default='local', max_length=30, verbose_name='Source'), - ), - migrations.AlterUniqueTogether( - name='user', - unique_together={('wecom_id',), ('slack_id',), ('dingtalk_id',), ('lark_id',), ('feishu_id',)}, - ), - ] diff --git a/apps/users/models/user.py b/apps/users/models/user.py index 58c5f6755..6cd20b7ab 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -4,8 +4,8 @@ import base64 import datetime import uuid -from typing import Callable from collections import defaultdict +from typing import Callable import sshpubkeys from django.conf import settings @@ -956,7 +956,10 @@ class User(AuthMixin, SourceMixin, TokenMixin, RoleMixin, MFAMixin, LabeledMixin @property def receive_backends(self): - return self.user_msg_subscription.receive_backends + try: + return self.user_msg_subscription.receive_backends + except: + return [] @property def is_otp_secret_key_bound(self):