diff --git a/apps/assets/forms/cmd_filter.py b/apps/assets/forms/cmd_filter.py index 6cb35e631..308a008d0 100644 --- a/apps/assets/forms/cmd_filter.py +++ b/apps/assets/forms/cmd_filter.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- # from django import forms +from django.core.exceptions import ValidationError +import re from orgs.mixins import OrgModelForm from ..models import CommandFilter, CommandFilterRule @@ -15,6 +17,8 @@ class CommandFilterForm(OrgModelForm): class CommandFilterRuleForm(OrgModelForm): + invalid_pattern = re.compile(r'[\.\*\+\[\\\?\{\}\^\$\|\(\)\#\<\>]') + class Meta: model = CommandFilterRule fields = [ @@ -25,3 +29,11 @@ class CommandFilterRuleForm(OrgModelForm): 'placeholder': 'eg:\r\nreboot\r\nrm -rf' }), } + + def clean_content(self): + content = self.cleaned_data.get("content") + if self.invalid_pattern.search(content): + invalid_char = self.invalid_pattern.pattern.replace('\\', '') + msg = _("Content should not be contain: {}").format(invalid_char) + raise ValidationError(msg) + return content diff --git a/apps/assets/migrations/0002_auto_20180105_1807.py b/apps/assets/migrations/0002_auto_20180105_1807.py deleted file mode 100644 index bf1f022ac..000000000 --- a/apps/assets/migrations/0002_auto_20180105_1807.py +++ /dev/null @@ -1,35 +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 - - -class Migration(migrations.Migration): - - 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'}, - ), - ] diff --git a/apps/assets/migrations/0003_auto_20180109_2331.py b/apps/assets/migrations/0003_auto_20180109_2331.py deleted file mode 100644 index 254de6236..000000000 --- a/apps/assets/migrations/0003_auto_20180109_2331.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11 on 2018-01-09 15:31 -from __future__ import unicode_literals - -import assets.models.asset -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('assets', '0002_auto_20180105_1807'), - ] - - operations = [ - migrations.AlterField( - model_name='asset', - name='cluster', - field=models.ForeignKey(default=assets.models.asset.default_cluster, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='assets', to='assets.Cluster', verbose_name='Cluster'), - ), - ] 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 009381bcb..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.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'), - ), - ] 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/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/0033_auto_20190624_2108.py b/apps/assets/migrations/0033_auto_20190624_2108.py index c9ac245d0..dc89bc125 100644 --- a/apps/assets/migrations/0033_auto_20190624_2108.py +++ b/apps/assets/migrations/0033_auto_20190624_2108.py @@ -1,6 +1,5 @@ # Generated by Django 2.1.7 on 2019-06-24 13:08 -import common.fields.model from django.db import migrations diff --git a/apps/assets/serializers/cmd_filter.py b/apps/assets/serializers/cmd_filter.py index b523a1779..e5ab62037 100644 --- a/apps/assets/serializers/cmd_filter.py +++ b/apps/assets/serializers/cmd_filter.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # +import re from rest_framework import serializers from common.fields import ChoiceDisplayField @@ -20,8 +21,16 @@ class CommandFilterSerializer(BulkOrgResourceModelSerializer): class CommandFilterRuleSerializer(BulkOrgResourceModelSerializer): serializer_choice_field = ChoiceDisplayField + invalid_pattern = re.compile(r'[\.\*\+\[\\\?\{\}\^\$\|\(\)\#\<\>]') class Meta: model = CommandFilterRule fields = '__all__' list_serializer_class = AdaptedBulkListSerializer + + def validate_content(self, content): + if self.invalid_pattern.search(content): + invalid_char = self.invalid_pattern.pattern.replace('\\', '') + msg = _("Content should not be contain: {}").format(invalid_char) + raise serializers.ValidationError(msg) + return content diff --git a/apps/common/mixins.py b/apps/common/mixins.py deleted file mode 100644 index b46673cd6..000000000 --- a/apps/common/mixins.py +++ /dev/null @@ -1,234 +0,0 @@ -# coding: utf-8 - -from django.db import models -from django.http import JsonResponse -from django.utils import timezone -from django.core.cache import cache -from django.utils.translation import ugettext_lazy as _ -from django.contrib import messages -from rest_framework.utils import html -from rest_framework.settings import api_settings -from rest_framework.exceptions import ValidationError -from rest_framework.fields import SkipField - -from .const import KEY_CACHE_RESOURCES_ID - - -class NoDeleteQuerySet(models.query.QuerySet): - - def delete(self): - return self.update(is_discard=True, discard_time=timezone.now()) - - -class NoDeleteManager(models.Manager): - - def get_all(self): - return NoDeleteQuerySet(self.model, using=self._db) - - def get_queryset(self): - return NoDeleteQuerySet(self.model, using=self._db).filter(is_discard=False) - - def get_deleted(self): - return NoDeleteQuerySet(self.model, using=self._db).filter(is_discard=True) - - -class NoDeleteModelMixin(models.Model): - is_discard = models.BooleanField(verbose_name=_("is discard"), default=False) - discard_time = models.DateTimeField(verbose_name=_("discard time"), null=True, blank=True) - - objects = NoDeleteManager() - - class Meta: - abstract = True - - def delete(self): - self.is_discard = True - self.discard_time = timezone.now() - return self.save() - - -class JSONResponseMixin(object): - """JSON mixin""" - @staticmethod - def render_json_response(context): - return JsonResponse(context) - - -class IDInFilterMixin(object): - def filter_queryset(self, queryset): - queryset = super(IDInFilterMixin, self).filter_queryset(queryset) - id_list = self.request.query_params.get('id__in') - if id_list: - import json - try: - ids = json.loads(id_list) - except Exception as e: - return queryset - if isinstance(ids, list): - queryset = queryset.filter(id__in=ids) - return queryset - - -class IDInCacheFilterMixin(object): - - def filter_queryset(self, queryset): - queryset = super(IDInCacheFilterMixin, self).filter_queryset(queryset) - spm = self.request.query_params.get('spm') - cache_key = KEY_CACHE_RESOURCES_ID.format(spm) - resources_id = cache.get(cache_key) - if resources_id and isinstance(resources_id, list): - queryset = queryset.filter(id__in=resources_id) - return queryset - - -class IDExportFilterMixin(object): - def filter_queryset(self, queryset): - # 下载导入模版 - if self.request.query_params.get('template') == 'import': - return [] - else: - return super(IDExportFilterMixin, self).filter_queryset(queryset) - - -class BulkSerializerMixin(object): - """ - Become rest_framework_bulk not support uuid as a primary key - so rewrite it. https://github.com/miki725/django-rest-framework-bulk/issues/66 - """ - def to_internal_value(self, data): - from rest_framework_bulk import BulkListSerializer - ret = super(BulkSerializerMixin, self).to_internal_value(data) - - id_attr = getattr(self.Meta, 'update_lookup_field', 'id') - if self.context.get('view'): - request_method = getattr(getattr(self.context.get('view'), 'request'), 'method', '') - # add update_lookup_field field back to validated data - # since super by default strips out read-only fields - # hence id will no longer be present in validated_data - if all((isinstance(self.root, BulkListSerializer), - id_attr, - request_method in ('PUT', 'PATCH'))): - id_field = self.fields[id_attr] - if data.get("id"): - id_value = id_field.to_internal_value(data.get("id")) - else: - id_value = id_field.to_internal_value(data.get("pk")) - ret[id_attr] = id_value - - return ret - - -class BulkListSerializerMixin(object): - """ - Become rest_framework_bulk doing bulk update raise Exception: - 'QuerySet' object has no attribute 'pk' when doing bulk update - so rewrite it . - https://github.com/miki725/django-rest-framework-bulk/issues/68 - """ - - def to_internal_value(self, data): - """ - List of dicts of native values <- List of dicts of primitive datatypes. - """ - if html.is_html_input(data): - data = html.parse_html_list(data) - - if not isinstance(data, list): - message = self.error_messages['not_a_list'].format( - input_type=type(data).__name__ - ) - raise ValidationError({ - api_settings.NON_FIELD_ERRORS_KEY: [message] - }, code='not_a_list') - - if not self.allow_empty and len(data) == 0: - if self.parent and self.partial: - raise SkipField() - - message = self.error_messages['empty'] - raise ValidationError({ - api_settings.NON_FIELD_ERRORS_KEY: [message] - }, code='empty') - - ret = [] - errors = [] - - for item in data: - try: - # prepare child serializer to only handle one instance - if 'id' in item.keys(): - self.child.instance = self.instance.get(id=item['id']) if self.instance else None - if 'pk' in item.keys(): - self.child.instance = self.instance.get(id=item['pk']) if self.instance else None - - self.child.initial_data = item - # raw - validated = self.child.run_validation(item) - except ValidationError as exc: - errors.append(exc.detail) - else: - ret.append(validated) - errors.append({}) - - if any(errors): - raise ValidationError(errors) - - return ret - - -class DatetimeSearchMixin: - date_format = '%Y-%m-%d' - date_from = date_to = None - - def get_date_range(self): - date_from_s = self.request.GET.get('date_from') - date_to_s = self.request.GET.get('date_to') - - if date_from_s: - date_from = timezone.datetime.strptime(date_from_s, self.date_format) - tz = timezone.get_current_timezone() - self.date_from = tz.localize(date_from) - else: - self.date_from = timezone.now() - timezone.timedelta(7) - - if date_to_s: - date_to = timezone.datetime.strptime( - date_to_s + ' 23:59:59', self.date_format + ' %H:%M:%S' - ) - self.date_to = date_to.replace( - tzinfo=timezone.get_current_timezone() - ) - else: - self.date_to = timezone.now() - - def get(self, request, *args, **kwargs): - self.get_date_range() - return super().get(request, *args, **kwargs) - - -class ApiMessageMixin: - success_message = _("%(name)s was %(action)s successfully") - _action_map = {"create": _("create"), "update": _("update")} - - def get_success_message(self, cleaned_data): - if not isinstance(cleaned_data, dict): - return '' - data = {k: v for k, v in cleaned_data.items()} - action = getattr(self, "action", "create") - data["action"] = self._action_map.get(action) - try: - message = self.success_message % data - except: - message = '' - return message - - def dispatch(self, request, *args, **kwargs): - resp = super().dispatch(request, *args, **kwargs) - if request.method.lower() in ("get", "delete", "patch"): - return resp - if resp.status_code >= 400: - return resp - message = self.get_success_message(resp.data) - if message: - messages.success(request, message) - return resp diff --git a/apps/common/mixins/__init__.py b/apps/common/mixins/__init__.py new file mode 100644 index 000000000..4249b3d64 --- /dev/null +++ b/apps/common/mixins/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- +# +from .models import * +from .serializers import * +from .api import * +from .views import * diff --git a/apps/common/mixins/api.py b/apps/common/mixins/api.py new file mode 100644 index 000000000..410f077eb --- /dev/null +++ b/apps/common/mixins/api.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# +from django.http import JsonResponse +from django.core.cache import cache +from django.utils.translation import ugettext_lazy as _ +from django.contrib import messages + +from ..const import KEY_CACHE_RESOURCES_ID + +__all__ = [ + "JSONResponseMixin", "IDInCacheFilterMixin", "IDExportFilterMixin", + "IDInFilterMixin", "ApiMessageMixin" +] + + +class JSONResponseMixin(object): + """JSON mixin""" + @staticmethod + def render_json_response(context): + return JsonResponse(context) + + +class IDInFilterMixin(object): + def filter_queryset(self, queryset): + queryset = super(IDInFilterMixin, self).filter_queryset(queryset) + id_list = self.request.query_params.get('id__in') + if id_list: + import json + try: + ids = json.loads(id_list) + except Exception as e: + return queryset + if isinstance(ids, list): + queryset = queryset.filter(id__in=ids) + return queryset + + +class IDInCacheFilterMixin(object): + + def filter_queryset(self, queryset): + queryset = super(IDInCacheFilterMixin, self).filter_queryset(queryset) + spm = self.request.query_params.get('spm') + cache_key = KEY_CACHE_RESOURCES_ID.format(spm) + resources_id = cache.get(cache_key) + if resources_id and isinstance(resources_id, list): + queryset = queryset.filter(id__in=resources_id) + return queryset + + +class IDExportFilterMixin(object): + def filter_queryset(self, queryset): + # 下载导入模版 + if self.request.query_params.get('template') == 'import': + return [] + else: + return super(IDExportFilterMixin, self).filter_queryset(queryset) + + +class ApiMessageMixin: + success_message = _("%(name)s was %(action)s successfully") + _action_map = {"create": _("create"), "update": _("update")} + + def get_success_message(self, cleaned_data): + if not isinstance(cleaned_data, dict): + return '' + data = {k: v for k, v in cleaned_data.items()} + action = getattr(self, "action", "create") + data["action"] = self._action_map.get(action) + try: + message = self.success_message % data + except: + message = '' + return message + + def dispatch(self, request, *args, **kwargs): + resp = super().dispatch(request, *args, **kwargs) + if request.method.lower() in ("get", "delete", "patch"): + return resp + if resp.status_code >= 400: + return resp + message = self.get_success_message(resp.data) + if message: + messages.success(request, message) + return resp \ No newline at end of file diff --git a/apps/common/mixins/models.py b/apps/common/mixins/models.py new file mode 100644 index 000000000..d4af23896 --- /dev/null +++ b/apps/common/mixins/models.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# + +from django.db import models +from django.utils import timezone +from django.utils.translation import ugettext_lazy as _ + + +__all__ = ["NoDeleteManager", "NoDeleteModelMixin", "NoDeleteQuerySet"] + + +class NoDeleteQuerySet(models.query.QuerySet): + + def delete(self): + return self.update(is_discard=True, discard_time=timezone.now()) + + +class NoDeleteManager(models.Manager): + + def get_all(self): + return NoDeleteQuerySet(self.model, using=self._db) + + def get_queryset(self): + return NoDeleteQuerySet(self.model, using=self._db).filter(is_discard=False) + + def get_deleted(self): + return NoDeleteQuerySet(self.model, using=self._db).filter(is_discard=True) + + +class NoDeleteModelMixin(models.Model): + is_discard = models.BooleanField(verbose_name=_("is discard"), default=False) + discard_time = models.DateTimeField(verbose_name=_("discard time"), null=True, blank=True) + + objects = NoDeleteManager() + + class Meta: + abstract = True + + def delete(self): + self.is_discard = True + self.discard_time = timezone.now() + return self.save() diff --git a/apps/common/mixins/serializers.py b/apps/common/mixins/serializers.py new file mode 100644 index 000000000..009d0b994 --- /dev/null +++ b/apps/common/mixins/serializers.py @@ -0,0 +1,95 @@ +# -*- coding: utf-8 -*- +# + +from rest_framework.utils import html +from rest_framework.settings import api_settings +from rest_framework.exceptions import ValidationError +from rest_framework.fields import SkipField + +__all__ = ['BulkSerializerMixin', 'BulkListSerializerMixin'] + + +class BulkSerializerMixin(object): + """ + Become rest_framework_bulk not support uuid as a primary key + so rewrite it. https://github.com/miki725/django-rest-framework-bulk/issues/66 + """ + def to_internal_value(self, data): + from rest_framework_bulk import BulkListSerializer + ret = super(BulkSerializerMixin, self).to_internal_value(data) + + id_attr = getattr(self.Meta, 'update_lookup_field', 'id') + if self.context.get('view'): + request_method = getattr(getattr(self.context.get('view'), 'request'), 'method', '') + # add update_lookup_field field back to validated data + # since super by default strips out read-only fields + # hence id will no longer be present in validated_data + if all((isinstance(self.root, BulkListSerializer), + id_attr, + request_method in ('PUT', 'PATCH'))): + id_field = self.fields[id_attr] + if data.get("id"): + id_value = id_field.to_internal_value(data.get("id")) + else: + id_value = id_field.to_internal_value(data.get("pk")) + ret[id_attr] = id_value + + return ret + + +class BulkListSerializerMixin(object): + """ + Become rest_framework_bulk doing bulk update raise Exception: + 'QuerySet' object has no attribute 'pk' when doing bulk update + so rewrite it . + https://github.com/miki725/django-rest-framework-bulk/issues/68 + """ + + def to_internal_value(self, data): + """ + List of dicts of native values <- List of dicts of primitive datatypes. + """ + if html.is_html_input(data): + data = html.parse_html_list(data) + + if not isinstance(data, list): + message = self.error_messages['not_a_list'].format( + input_type=type(data).__name__ + ) + raise ValidationError({ + api_settings.NON_FIELD_ERRORS_KEY: [message] + }, code='not_a_list') + + if not self.allow_empty and len(data) == 0: + if self.parent and self.partial: + raise SkipField() + + message = self.error_messages['empty'] + raise ValidationError({ + api_settings.NON_FIELD_ERRORS_KEY: [message] + }, code='empty') + + ret = [] + errors = [] + + for item in data: + try: + # prepare child serializer to only handle one instance + if 'id' in item.keys(): + self.child.instance = self.instance.get(id=item['id']) if self.instance else None + if 'pk' in item.keys(): + self.child.instance = self.instance.get(id=item['pk']) if self.instance else None + + self.child.initial_data = item + # raw + validated = self.child.run_validation(item) + except ValidationError as exc: + errors.append(exc.detail) + else: + ret.append(validated) + errors.append({}) + + if any(errors): + raise ValidationError(errors) + + return ret diff --git a/apps/common/mixins/views.py b/apps/common/mixins/views.py new file mode 100644 index 000000000..a00535b5b --- /dev/null +++ b/apps/common/mixins/views.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# +# coding: utf-8 + +from django.utils import timezone + + +__all__ = ["DatetimeSearchMixin"] + + +class DatetimeSearchMixin: + date_format = '%Y-%m-%d' + date_from = date_to = None + + def get_date_range(self): + date_from_s = self.request.GET.get('date_from') + date_to_s = self.request.GET.get('date_to') + + if date_from_s: + date_from = timezone.datetime.strptime(date_from_s, self.date_format) + tz = timezone.get_current_timezone() + self.date_from = tz.localize(date_from) + else: + self.date_from = timezone.now() - timezone.timedelta(7) + + if date_to_s: + date_to = timezone.datetime.strptime( + date_to_s + ' 23:59:59', self.date_format + ' %H:%M:%S' + ) + self.date_to = date_to.replace( + tzinfo=timezone.get_current_timezone() + ) + else: + self.date_to = timezone.now() + + def get(self, request, *args, **kwargs): + self.get_date_range() + return super().get(request, *args, **kwargs) + + diff --git a/apps/jumpserver/settings.py b/apps/jumpserver/settings.py index 0ca68d947..0f9f7df55 100644 --- a/apps/jumpserver/settings.py +++ b/apps/jumpserver/settings.py @@ -301,10 +301,10 @@ LOGGING = { 'handlers': ['gunicorn_console', 'gunicorn_file'], 'level': 'INFO', }, - # 'django.db': { - # 'handlers': ['console', 'file'], - # 'level': 'DEBUG' - # } + 'django.db': { + 'handlers': ['console', 'file'], + 'level': 'DEBUG' + } } } diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 3f803b786..056de6126 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: Jumpserver 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-06-28 20:08+0800\n" +"POT-Creation-Date: 2019-07-02 14:47+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: ibuler \n" "Language-Team: Jumpserver team\n" @@ -86,7 +86,7 @@ msgstr "运行参数" #: assets/templates/assets/system_user_list.html:55 audits/models.py:19 #: audits/templates/audits/ftp_log_list.html:41 #: audits/templates/audits/ftp_log_list.html:71 -#: perms/forms/asset_permission.py:47 perms/models/asset_permission.py:53 +#: perms/forms/asset_permission.py:68 perms/models/asset_permission.py:85 #: perms/templates/perms/asset_permission_create_update.html:45 #: perms/templates/perms/asset_permission_list.html:48 #: perms/templates/perms/asset_permission_list.html:117 @@ -115,8 +115,8 @@ msgstr "资产" #: assets/models/user.py:160 assets/templates/assets/user_asset_list.html:172 #: audits/models.py:20 audits/templates/audits/ftp_log_list.html:49 #: audits/templates/audits/ftp_log_list.html:72 -#: perms/forms/asset_permission.py:53 perms/models/asset_permission.py:55 -#: perms/models/asset_permission.py:76 +#: perms/forms/asset_permission.py:74 perms/models/asset_permission.py:87 +#: perms/models/asset_permission.py:104 #: perms/templates/perms/asset_permission_detail.html:140 #: perms/templates/perms/asset_permission_list.html:50 #: perms/templates/perms/asset_permission_list.html:71 @@ -149,7 +149,7 @@ msgstr "系统用户" #: assets/templates/assets/system_user_detail.html:58 #: assets/templates/assets/system_user_list.html:51 ops/models/adhoc.py:37 #: ops/templates/ops/task_detail.html:60 ops/templates/ops/task_list.html:27 -#: orgs/models.py:11 perms/models/asset_permission.py:22 +#: orgs/models.py:11 perms/models/asset_permission.py:23 #: perms/models/base.py:35 #: perms/templates/perms/asset_permission_detail.html:62 #: perms/templates/perms/asset_permission_list.html:45 @@ -215,10 +215,10 @@ msgstr "参数" #: assets/templates/assets/domain_detail.html:72 #: assets/templates/assets/system_user_detail.html:100 #: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:14 -#: perms/models/asset_permission.py:79 perms/models/base.py:41 +#: perms/models/asset_permission.py:107 perms/models/base.py:41 #: perms/templates/perms/asset_permission_detail.html:98 #: perms/templates/perms/remote_app_permission_detail.html:90 -#: users/models/user.py:105 users/serializers/v1.py:99 +#: users/models/user.py:105 users/serializers/v1.py:107 #: users/templates/users/user_detail.html:111 #: xpack/plugins/change_auth_plan/models.py:106 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113 @@ -238,7 +238,7 @@ msgstr "创建者" #: assets/templates/assets/domain_detail.html:68 #: assets/templates/assets/system_user_detail.html:96 #: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:64 -#: orgs/models.py:15 perms/models/asset_permission.py:80 +#: orgs/models.py:15 perms/models/asset_permission.py:108 #: perms/models/base.py:42 #: perms/templates/perms/asset_permission_detail.html:94 #: perms/templates/perms/remote_app_permission_detail.html:86 @@ -274,7 +274,7 @@ msgstr "创建日期" #: assets/templates/assets/system_user_detail.html:104 #: assets/templates/assets/system_user_list.html:59 #: assets/templates/assets/user_asset_list.html:175 ops/models/adhoc.py:43 -#: orgs/models.py:16 perms/models/asset_permission.py:81 +#: orgs/models.py:16 perms/models/asset_permission.py:109 #: perms/models/base.py:43 #: perms/templates/perms/asset_permission_detail.html:102 #: perms/templates/perms/remote_app_permission_detail.html:94 @@ -440,7 +440,6 @@ msgstr "详情" #: users/templates/users/user_group_list.html:20 #: users/templates/users/user_group_list.html:70 #: users/templates/users/user_list.html:20 -#: users/templates/users/user_list.html:96 #: users/templates/users/user_list.html:99 #: users/templates/users/user_profile.html:177 #: users/templates/users/user_profile.html:187 @@ -481,7 +480,6 @@ msgstr "更新" #: users/templates/users/user_detail.html:30 #: users/templates/users/user_group_detail.html:32 #: users/templates/users/user_group_list.html:72 -#: users/templates/users/user_list.html:104 #: users/templates/users/user_list.html:108 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:33 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:57 @@ -529,8 +527,7 @@ msgstr "创建远程应用" #: audits/templates/audits/operate_log_list.html:67 #: ops/templates/ops/adhoc_history.html:59 ops/templates/ops/task_adhoc.html:64 #: ops/templates/ops/task_history.html:65 ops/templates/ops/task_list.html:34 -#: perms/forms/asset_permission.py:56 perms/models/asset_permission.py:26 -#: perms/models/asset_permission.py:57 +#: perms/forms/asset_permission.py:21 perms/models/asset_permission.py:27 #: perms/templates/perms/asset_permission_create_update.html:50 #: perms/templates/perms/asset_permission_list.html:52 #: perms/templates/perms/asset_permission_list.html:126 @@ -552,7 +549,7 @@ msgstr "动作" #: applications/templates/applications/user_remote_app_list.html:57 #: assets/templates/assets/user_asset_list.html:100 perms/const.py:19 -#: perms/models/asset_permission.py:45 +#: perms/models/asset_permission.py:46 msgid "Connect" msgstr "连接" @@ -591,11 +588,11 @@ msgstr "请选择需要更新的资产" msgid "You can't update the root node name" msgstr "不能修改根节点名称" -#: assets/api/node.py:281 +#: assets/api/node.py:283 msgid "Update node asset hardware information: {}" msgstr "更新节点资产硬件信息: {}" -#: assets/api/node.py:295 +#: assets/api/node.py:297 msgid "Test if the assets under the node are connectable: {}" msgstr "测试节点下资产是否可连接: {}" @@ -622,7 +619,7 @@ msgstr "未知" #: assets/templates/assets/asset_detail.html:194 #: assets/templates/assets/asset_detail.html:202 #: assets/templates/assets/system_user_assets.html:83 -#: perms/models/asset_permission.py:54 +#: perms/models/asset_permission.py:86 #: xpack/plugins/change_auth_plan/models.py:72 msgid "Nodes" msgstr "节点" @@ -656,8 +653,8 @@ msgstr "网域" #: assets/forms/asset.py:64 assets/forms/asset.py:86 assets/forms/asset.py:99 #: assets/forms/asset.py:134 assets/models/node.py:248 #: assets/templates/assets/asset_create.html:42 -#: perms/forms/asset_permission.py:50 perms/forms/asset_permission.py:60 -#: perms/models/asset_permission.py:74 +#: perms/forms/asset_permission.py:71 perms/forms/asset_permission.py:79 +#: perms/models/asset_permission.py:102 #: perms/templates/perms/asset_permission_list.html:49 #: perms/templates/perms/asset_permission_list.html:70 #: perms/templates/perms/asset_permission_list.html:120 @@ -695,6 +692,10 @@ msgstr "如果有多个的互相隔离的网络,设置资产属于的网域, msgid "Select assets" msgstr "选择资产" +#: assets/forms/cmd_filter.py:37 assets/serializers/cmd_filter.py:34 +msgid "Content should not be contain: {}" +msgstr "内容不能包含: {}" + #: assets/forms/domain.py:51 msgid "Password should not contain special characters" msgstr "不能包含特殊字符" @@ -1000,7 +1001,7 @@ msgid "Operator" msgstr "运营商" #: assets/models/cluster.py:36 assets/models/group.py:34 -#: perms/utils/asset_permission.py:67 +#: perms/utils/asset_permission.py:106 msgid "Default" msgstr "默认" @@ -1112,7 +1113,7 @@ msgstr "默认资产组" #: audits/templates/audits/password_change_log_list.html:50 #: ops/templates/ops/command_execution_list.html:35 #: ops/templates/ops/command_execution_list.html:60 -#: perms/forms/asset_permission.py:41 perms/forms/remote_app_permission.py:31 +#: perms/forms/asset_permission.py:62 perms/forms/remote_app_permission.py:31 #: perms/models/base.py:36 #: perms/templates/perms/asset_permission_create_update.html:41 #: perms/templates/perms/asset_permission_list.html:46 @@ -1124,9 +1125,9 @@ msgstr "默认资产组" #: terminal/templates/terminal/command_list.html:72 #: terminal/templates/terminal/session_list.html:33 #: terminal/templates/terminal/session_list.html:71 users/forms.py:301 -#: users/models/user.py:38 users/models/user.py:431 users/serializers/v1.py:88 +#: users/models/user.py:38 users/models/user.py:431 users/serializers/v1.py:96 #: users/templates/users/user_group_detail.html:78 -#: users/templates/users/user_group_list.html:36 users/views/user.py:407 +#: users/templates/users/user_group_list.html:36 users/views/user.py:264 #: xpack/plugins/orgs/forms.py:26 #: xpack/plugins/orgs/templates/orgs/org_detail.html:113 #: xpack/plugins/orgs/templates/orgs/org_list.html:14 @@ -1205,26 +1206,25 @@ msgstr "登录模式" msgid "%(value)s is not an even number" msgstr "%(value)s is not an even number" -#: assets/serializers/admin_user.py:36 assets/serializers/asset.py:47 +#: assets/serializers/admin_user.py:36 assets/serializers/asset.py:46 #: assets/serializers/asset_user.py:30 assets/serializers/system_user.py:30 #: assets/templates/assets/_asset_user_list.html:18 msgid "Connectivity" msgstr "连接" -#: assets/serializers/asset.py:45 assets/serializers/asset.py:155 -#: assets/templates/assets/asset_create.html:24 +#: assets/serializers/asset.py:44 assets/templates/assets/asset_create.html:24 msgid "Protocols" msgstr "协议组" -#: assets/serializers/asset.py:73 +#: assets/serializers/asset.py:72 msgid "Hardware info" msgstr "硬件信息" -#: assets/serializers/asset.py:74 orgs/mixins.py:192 +#: assets/serializers/asset.py:73 orgs/mixins.py:192 msgid "Org name" msgstr "组织名称" -#: assets/serializers/asset.py:92 +#: assets/serializers/asset.py:91 msgid "Protocol duplicate: {}" msgstr "协议重复: {}" @@ -1710,7 +1710,7 @@ msgstr "创建日期" #: assets/templates/assets/asset_detail.html:154 #: assets/templates/assets/user_asset_list.html:46 -#: perms/models/asset_permission.py:77 perms/models/base.py:38 +#: perms/models/asset_permission.py:105 perms/models/base.py:38 #: perms/templates/perms/asset_permission_create_update.html:55 #: perms/templates/perms/asset_permission_detail.html:120 #: perms/templates/perms/remote_app_permission_create_update.html:54 @@ -2056,10 +2056,6 @@ msgstr "批量更新资产" msgid "Update asset" msgstr "更新资产" -#: assets/views/asset.py:347 -msgid "already exists" -msgstr "已经存在" - #: assets/views/cmd_filter.py:32 msgid "Command filter list" msgstr "命令过滤器列表" @@ -2557,8 +2553,8 @@ msgstr "欢迎回来,请输入用户名和密码登录" msgid "Please enable cookies and try again." msgstr "设置你的浏览器支持cookie" -#: authentication/views/login.py:172 users/views/user.py:555 -#: users/views/user.py:580 +#: authentication/views/login.py:172 users/views/user.py:412 +#: users/views/user.py:437 msgid "MFA code invalid, or ntp sync server time" msgstr "MFA验证码不正确,或者服务器端时间不对" @@ -3000,11 +2996,11 @@ msgstr "命令执行" msgid "Organization" msgstr "组织" -#: perms/const.py:18 perms/models/asset_permission.py:44 settings/forms.py:143 +#: perms/const.py:18 perms/models/asset_permission.py:45 settings/forms.py:143 msgid "All" msgstr "全部" -#: perms/const.py:20 perms/models/asset_permission.py:46 +#: perms/const.py:20 perms/models/asset_permission.py:47 msgid "Upload file" msgstr "上传文件" @@ -3012,8 +3008,8 @@ msgstr "上传文件" msgid "Download file" msgstr "下载文件" -#: perms/forms/asset_permission.py:44 perms/forms/remote_app_permission.py:34 -#: perms/models/asset_permission.py:75 perms/models/base.py:37 +#: perms/forms/asset_permission.py:65 perms/forms/remote_app_permission.py:34 +#: perms/models/asset_permission.py:103 perms/models/base.py:37 #: perms/templates/perms/asset_permission_list.html:47 #: perms/templates/perms/asset_permission_list.html:67 #: perms/templates/perms/asset_permission_list.html:114 @@ -3026,30 +3022,34 @@ msgstr "下载文件" msgid "User group" msgstr "用户组" -#: perms/forms/asset_permission.py:63 +#: perms/forms/asset_permission.py:82 msgid "" "Tips: The RDP protocol does not support separate controls for uploading or " "downloading files" msgstr "提示:RDP 协议不支持单独控制上传或下载文件" -#: perms/forms/asset_permission.py:73 perms/forms/remote_app_permission.py:47 +#: perms/forms/asset_permission.py:92 perms/forms/remote_app_permission.py:47 msgid "User or group at least one required" msgstr "用户和用户组至少选一个" -#: perms/forms/asset_permission.py:82 +#: perms/forms/asset_permission.py:101 msgid "Asset or group at least one required" msgstr "资产和节点至少选一个" -#: perms/models/asset_permission.py:47 +#: perms/models/asset_permission.py:49 msgid "Upload download" msgstr "上传下载" -#: perms/models/asset_permission.py:61 perms/models/asset_permission.py:87 +#: perms/models/asset_permission.py:89 +msgid "Actions" +msgstr "动作" + +#: perms/models/asset_permission.py:93 perms/models/asset_permission.py:115 #: templates/_nav.html:44 msgid "Asset permission" msgstr "资产授权" -#: perms/models/asset_permission.py:78 perms/models/base.py:40 +#: perms/models/asset_permission.py:106 perms/models/base.py:40 #: perms/templates/perms/asset_permission_detail.html:90 #: perms/templates/perms/remote_app_permission_detail.html:82 #: users/models/user.py:102 users/templates/users/user_detail.html:107 @@ -3199,8 +3199,8 @@ msgid "Add user group to this permission" msgstr "添加用户组" #: perms/views/asset_permission.py:34 perms/views/asset_permission.py:65 -#: perms/views/asset_permission.py:81 perms/views/asset_permission.py:97 -#: perms/views/asset_permission.py:134 perms/views/asset_permission.py:167 +#: perms/views/asset_permission.py:82 perms/views/asset_permission.py:99 +#: perms/views/asset_permission.py:136 perms/views/asset_permission.py:169 #: perms/views/remote_app_permission.py:33 #: perms/views/remote_app_permission.py:49 #: perms/views/remote_app_permission.py:65 @@ -3219,19 +3219,19 @@ msgstr "资产授权列表" msgid "Create asset permission" msgstr "创建权限规则" -#: perms/views/asset_permission.py:82 +#: perms/views/asset_permission.py:83 msgid "Update asset permission" msgstr "更新资产授权" -#: perms/views/asset_permission.py:98 +#: perms/views/asset_permission.py:100 msgid "Asset permission detail" msgstr "资产授权详情" -#: perms/views/asset_permission.py:135 +#: perms/views/asset_permission.py:137 msgid "Asset permission user list" msgstr "资产授权用户列表" -#: perms/views/asset_permission.py:168 +#: perms/views/asset_permission.py:170 msgid "Asset permission asset list" msgstr "资产授权资产列表" @@ -3828,7 +3828,7 @@ msgstr "商业支持" #: users/templates/users/user_profile.html:17 #: users/templates/users/user_profile_update.html:37 #: users/templates/users/user_profile_update.html:57 -#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:388 +#: users/templates/users/user_pubkey_update.html:37 users/views/user.py:245 msgid "Profile" msgstr "个人信息" @@ -3923,13 +3923,13 @@ msgstr "" #: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:45 #: users/views/group.py:62 users/views/group.py:79 users/views/group.py:96 -#: users/views/login.py:154 users/views/user.py:70 users/views/user.py:87 -#: users/views/user.py:131 users/views/user.py:211 users/views/user.py:374 -#: users/views/user.py:426 users/views/user.py:467 +#: users/views/login.py:154 users/views/user.py:68 users/views/user.py:85 +#: users/views/user.py:129 users/views/user.py:209 users/views/user.py:231 +#: users/views/user.py:283 users/views/user.py:324 msgid "Users" msgstr "用户管理" -#: templates/_nav.html:13 users/views/user.py:71 +#: templates/_nav.html:13 users/views/user.py:69 msgid "User list" msgstr "用户列表" @@ -4369,11 +4369,11 @@ msgid "" "You should use your ssh client tools connect terminal: {}

{}" msgstr "你可以使用ssh客户端工具连接终端" -#: users/api/user.py:79 users/api/user.py:90 users/api/user.py:116 +#: users/api/user.py:93 msgid "You do not have permission." msgstr "你没有权限" -#: users/api/user.py:221 +#: users/api/user.py:186 msgid "Could not reset self otp, use profile reset instead" msgstr "不能再该页面重置MFA, 请去个人信息页面重置" @@ -4405,7 +4405,7 @@ msgstr "添加到用户组" msgid "Public key should not be the same as your old one." msgstr "不能和原来的密钥相同" -#: users/forms.py:90 users/forms.py:237 users/serializers/v1.py:74 +#: users/forms.py:90 users/forms.py:237 users/serializers/v1.py:82 msgid "Not a valid ssh public key" msgstr "ssh密钥不合法" @@ -4532,7 +4532,7 @@ msgid "Date password last updated" msgstr "最后更新密码日期" #: users/models/user.py:139 users/templates/users/user_update.html:22 -#: users/views/login.py:46 users/views/login.py:107 users/views/user.py:439 +#: users/views/login.py:46 users/views/login.py:107 users/views/user.py:296 msgid "User auth from {}, go there change password" msgstr "用户认证源来自 {}, 请去相应系统修改密码" @@ -4569,10 +4569,12 @@ msgid "Avatar url" msgstr "头像路径" #: users/serializers/v1.py:46 -#, fuzzy -#| msgid "Password does not match" +msgid "Role limit to {}" +msgstr "角色只能为 {}" + +#: users/serializers/v1.py:54 msgid "Password does not match security rules" -msgstr "密码不一致" +msgstr "密码不满足安全规则" #: users/serializers_v2/user.py:36 msgid "name not unique" @@ -4624,7 +4626,7 @@ msgid "Import users" msgstr "导入用户" #: users/templates/users/_user_update_modal.html:4 -#: users/templates/users/user_update.html:4 users/views/user.py:132 +#: users/templates/users/user_update.html:4 users/views/user.py:130 msgid "Update user" msgstr "更新用户" @@ -4762,12 +4764,12 @@ msgid "Very strong" msgstr "很强" #: users/templates/users/user_create.html:4 -#: users/templates/users/user_list.html:28 users/views/user.py:88 +#: users/templates/users/user_list.html:28 users/views/user.py:86 msgid "Create user" msgstr "创建用户" #: users/templates/users/user_detail.html:19 -#: users/templates/users/user_granted_asset.html:18 users/views/user.py:212 +#: users/templates/users/user_granted_asset.html:18 users/views/user.py:210 msgid "User detail" msgstr "用户详情" @@ -4967,8 +4969,7 @@ msgstr "安装完成后点击下一步进入绑定页面(如已安装,直接 msgid "Administrator Settings force MFA login" msgstr "管理员设置强制使用MFA登录" -#: users/templates/users/user_profile.html:120 users/views/user.py:248 -#: users/views/user.py:303 +#: users/templates/users/user_profile.html:120 msgid "User groups" msgstr "用户组" @@ -5243,7 +5244,7 @@ msgstr "Token错误或失效" msgid "Password not same" msgstr "密码不一致" -#: users/views/login.py:114 users/views/user.py:146 users/views/user.py:449 +#: users/views/login.py:114 users/views/user.py:144 users/views/user.py:306 msgid "* Your password does not meet the requirements" msgstr "* 您的密码不符合要求" @@ -5251,51 +5252,47 @@ msgstr "* 您的密码不符合要求" msgid "First login" msgstr "首次登录" -#: users/views/user.py:163 +#: users/views/user.py:161 msgid "Bulk update user success" msgstr "批量更新用户成功" -#: users/views/user.py:191 +#: users/views/user.py:189 msgid "Bulk update user" msgstr "批量更新用户" -#: users/views/user.py:278 -msgid "Invalid file." -msgstr "文件不合法" - -#: users/views/user.py:375 +#: users/views/user.py:232 msgid "User granted assets" msgstr "用户授权资产" -#: users/views/user.py:408 +#: users/views/user.py:265 msgid "Profile setting" msgstr "个人信息设置" -#: users/views/user.py:427 +#: users/views/user.py:284 msgid "Password update" msgstr "密码更新" -#: users/views/user.py:468 +#: users/views/user.py:325 msgid "Public key update" msgstr "密钥更新" -#: users/views/user.py:510 +#: users/views/user.py:367 msgid "Password invalid" msgstr "用户名或密码无效" -#: users/views/user.py:610 +#: users/views/user.py:467 msgid "MFA enable success" msgstr "MFA 绑定成功" -#: users/views/user.py:611 +#: users/views/user.py:468 msgid "MFA enable success, return login page" msgstr "MFA 绑定成功,返回到登录页面" -#: users/views/user.py:613 +#: users/views/user.py:470 msgid "MFA disable success" msgstr "MFA 解绑成功" -#: users/views/user.py:614 +#: users/views/user.py:471 msgid "MFA disable success, return login page" msgstr "MFA 解绑成功,返回登录页面" @@ -5783,10 +5780,8 @@ msgid "Restore default failed." msgstr "恢复默认失败!" #: xpack/plugins/interface/views.py:24 -#, fuzzy -#| msgid "Interval" msgid "Interface" -msgstr "间隔" +msgstr "界面" #: xpack/plugins/interface/views.py:51 msgid "It is already in the default setting state!" @@ -5946,6 +5941,12 @@ msgstr "密码匣子" msgid "vault create" msgstr "创建" +#~ msgid "already exists" +#~ msgstr "已经存在" + +#~ msgid "Invalid file." +#~ msgstr "文件不合法" + #~ msgid "Refresh all node assets amount" #~ msgstr "刷新所有节点资产数量" diff --git a/apps/perms/api/asset_permission.py b/apps/perms/api/asset_permission.py index 267d83971..38e44abd0 100644 --- a/apps/perms/api/asset_permission.py +++ b/apps/perms/api/asset_permission.py @@ -10,7 +10,7 @@ from rest_framework.pagination import LimitOffsetPagination from common.permissions import IsOrgAdmin from common.utils import get_object_or_none -from ..models import AssetPermission, Action +from ..models import AssetPermission from ..hands import ( User, UserGroup, Asset, Node, SystemUser, ) diff --git a/apps/perms/api/user_permission.py b/apps/perms/api/user_permission.py index 2a2272536..666b7f55a 100644 --- a/apps/perms/api/user_permission.py +++ b/apps/perms/api/user_permission.py @@ -21,7 +21,7 @@ from ..utils import ( from ..hands import User, Asset, Node, SystemUser, NodeSerializer from .. import serializers, const from ..mixins import AssetsFilterMixin -from ..models import ActionFlag +from ..models import Action logger = get_logger(__name__) @@ -423,7 +423,7 @@ class ValidateUserAssetPermissionApi(UserPermissionCacheMixin, APIView): return Response({'msg': False}, status=403) action = granted_system_users[su] - choices = ActionFlag.value_to_choices(action) + choices = Action.value_to_choices(action) if action_name not in choices: return Response({'msg': False}, status=403) diff --git a/apps/perms/const.py b/apps/perms/const.py index 457db580c..23d2ba044 100644 --- a/apps/perms/const.py +++ b/apps/perms/const.py @@ -1,24 +1,4 @@ # -*- coding: utf-8 -*- # -from django.utils.translation import ugettext_lazy as _ - -__all__ = [ - 'PERMS_ACTION_NAME_ALL', 'PERMS_ACTION_NAME_CONNECT', - 'PERMS_ACTION_NAME_DOWNLOAD_FILE', 'PERMS_ACTION_NAME_UPLOAD_FILE', - 'PERMS_ACTION_NAME_CHOICES' -] - -PERMS_ACTION_NAME_ALL = 'all' -PERMS_ACTION_NAME_CONNECT = 'connect' -PERMS_ACTION_NAME_UPLOAD_FILE = 'upload_file' -PERMS_ACTION_NAME_DOWNLOAD_FILE = 'download_file' - -PERMS_ACTION_NAME_CHOICES = ( - (PERMS_ACTION_NAME_ALL, _('All')), - (PERMS_ACTION_NAME_CONNECT, _('Connect')), - (PERMS_ACTION_NAME_UPLOAD_FILE, _('Upload file')), - (PERMS_ACTION_NAME_DOWNLOAD_FILE, _('Download file')), -) - -UNGROUPED_NODE_ID = "00000000-0000-0000-0000-000000000000" +UNGROUPED_NODE_ID = "00000000-0000-0000-0000-000000000002" diff --git a/apps/perms/forms/asset_permission.py b/apps/perms/forms/asset_permission.py index fb63517ff..c061f8d2a 100644 --- a/apps/perms/forms/asset_permission.py +++ b/apps/perms/forms/asset_permission.py @@ -7,7 +7,7 @@ from django.utils.translation import ugettext_lazy as _ from orgs.mixins import OrgModelForm from orgs.utils import current_org from assets.models import Asset, Node -from ..models import AssetPermission, ActionFlag +from ..models import AssetPermission, Action __all__ = [ 'AssetPermissionForm', @@ -16,20 +16,20 @@ __all__ = [ class ActionField(forms.MultipleChoiceField): def __init__(self, *args, **kwargs): - kwargs['choices'] = ActionFlag.CHOICES - kwargs['initial'] = ActionFlag.ALL + kwargs['choices'] = Action.CHOICES + kwargs['initial'] = Action.ALL kwargs['label'] = _("Action") kwargs['widget'] = forms.CheckboxSelectMultiple() super().__init__(*args, **kwargs) def to_python(self, value): value = super().to_python(value) - return ActionFlag.choices_to_value(value) + return Action.choices_to_value(value) def prepare_value(self, value): if value is None: return value - value = ActionFlag.value_to_choices(value) + value = Action.value_to_choices(value) return value diff --git a/apps/perms/migrations/0003_action.py b/apps/perms/migrations/0003_action.py index 41c0f9f39..c9dea7736 100644 --- a/apps/perms/migrations/0003_action.py +++ b/apps/perms/migrations/0003_action.py @@ -4,14 +4,6 @@ from django.db import migrations, models import uuid -def add_default_actions(apps, schema_editor): - from ..const import PERMS_ACTION_NAME_CHOICES - action_model = apps.get_model('perms', 'Action') - db_alias = schema_editor.connection.alias - for action, _ in PERMS_ACTION_NAME_CHOICES: - action_model.objects.using(db_alias).update_or_create(name=action) - - class Migration(migrations.Migration): dependencies = [ @@ -29,5 +21,4 @@ class Migration(migrations.Migration): 'verbose_name': 'Action', }, ), - migrations.RunPython(add_default_actions) ] diff --git a/apps/perms/migrations/0004_assetpermission_actions.py b/apps/perms/migrations/0004_assetpermission_actions.py index be468e7f0..dfe07f317 100644 --- a/apps/perms/migrations/0004_assetpermission_actions.py +++ b/apps/perms/migrations/0004_assetpermission_actions.py @@ -3,18 +3,6 @@ from django.db import migrations, models -def set_default_action_to_existing_perms(apps, schema_editor): - from orgs.utils import set_to_root_org - from ..models import Action - 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() - default_action = Action.get_action_all() - for perm in perms: - perm.actions.add(default_action.id) - - class Migration(migrations.Migration): dependencies = [ @@ -27,5 +15,4 @@ class Migration(migrations.Migration): name='actions', field=models.ManyToManyField(blank=True, related_name='permissions', to='perms.Action', verbose_name='Action'), ), - migrations.RunPython(set_default_action_to_existing_perms) ] diff --git a/apps/perms/migrations/0006_auto_20190628_1921.py b/apps/perms/migrations/0006_auto_20190628_1921.py index 0ea832751..f0faec017 100644 --- a/apps/perms/migrations/0006_auto_20190628_1921.py +++ b/apps/perms/migrations/0006_auto_20190628_1921.py @@ -6,21 +6,22 @@ from functools import reduce def migrate_old_actions(apps, schema_editor): from orgs.utils import set_to_root_org - from ..models import ActionFlag 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": ActionFlag.ALL, - "connect": ActionFlag.CONNECT, - "upload_file": ActionFlag.UPLOAD, - "download_file": ActionFlag.DOWNLOAD, + "all": 0b11111111, + "connect": 0b00000001, + "upload_file": 0b00000010, + "download_file": 0b00000100, } for perm in perms: actions = perm.actions.all() - new_actions = [actions_map.get(action.name, ActionFlag.ALL) for action in actions] + 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() diff --git a/apps/perms/migrations/0007_remove_assetpermission_actions.py b/apps/perms/migrations/0007_remove_assetpermission_actions.py index 63391ff85..1d8b3fbbb 100644 --- a/apps/perms/migrations/0007_remove_assetpermission_actions.py +++ b/apps/perms/migrations/0007_remove_assetpermission_actions.py @@ -19,4 +19,5 @@ class Migration(migrations.Migration): old_name='action', new_name='actions', ), + migrations.DeleteModel(name='Action'), ] diff --git a/apps/perms/models/asset_permission.py b/apps/perms/models/asset_permission.py index aba64ee0c..29d8d10ec 100644 --- a/apps/perms/models/asset_permission.py +++ b/apps/perms/models/asset_permission.py @@ -4,37 +4,18 @@ from functools import reduce from django.db import models from django.utils.translation import ugettext_lazy as _ -from common.utils import date_expired_default, set_or_append_attr_bulk +from common.utils import date_expired_default from orgs.mixins import OrgModelMixin -from ..const import PERMS_ACTION_NAME_CHOICES, PERMS_ACTION_NAME_ALL from .base import BasePermission __all__ = [ - 'Action', 'AssetPermission', 'NodePermission', 'ActionFlag' + 'AssetPermission', 'NodePermission', 'Action', ] -class Action(models.Model): - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField( - max_length=128, unique=True, choices=PERMS_ACTION_NAME_CHOICES, - verbose_name=_('Name') - ) - - class Meta: - verbose_name = _('Action') - - def __str__(self): - return self.get_name_display() - - @classmethod - def get_action_all(cls): - return cls.objects.get(name=PERMS_ACTION_NAME_ALL) - - -class ActionFlag: +class Action: CONNECT = 0b00000001 UPLOAD = 0b00000010 DOWNLOAD = 0b00000100 @@ -74,6 +55,8 @@ class ActionFlag: x = cls.NAME_MAP_REVERSE.get(x, 0) y = cls.NAME_MAP_REVERSE.get(y, 0) return x | y + if not value: + return None return reduce(to_choices, value) @classmethod @@ -86,7 +69,7 @@ class AssetPermission(BasePermission): nodes = models.ManyToManyField('assets.Node', related_name='granted_by_permissions', blank=True, verbose_name=_("Nodes")) system_users = models.ManyToManyField('assets.SystemUser', related_name='granted_by_permissions', verbose_name=_("System user")) # actions = models.ManyToManyField(Action, related_name='permissions', blank=True, verbose_name=_('Action')) - actions = models.IntegerField(choices=ActionFlag.DB_CHOICES, default=ActionFlag.ALL, verbose_name=_("Actions")) + actions = models.IntegerField(choices=Action.DB_CHOICES, default=Action.ALL, verbose_name=_("Actions")) class Meta: unique_together = [('org_id', 'name')] diff --git a/apps/perms/serializers/asset_permission.py b/apps/perms/serializers/asset_permission.py index 5a770b527..ecbed669b 100644 --- a/apps/perms/serializers/asset_permission.py +++ b/apps/perms/serializers/asset_permission.py @@ -5,36 +5,38 @@ from rest_framework import serializers from common.fields import StringManyToManyField from orgs.mixins import BulkOrgResourceModelSerializer -from perms.models import AssetPermission, ActionFlag +from perms.models import AssetPermission, Action __all__ = [ 'AssetPermissionCreateUpdateSerializer', 'AssetPermissionListSerializer', 'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer', - 'ActionField', + 'ActionsField', ] -class ActionField(serializers.MultipleChoiceField): +class ActionsField(serializers.MultipleChoiceField): def __init__(self, *args, **kwargs): - kwargs['choices'] = ActionFlag.CHOICES + kwargs['choices'] = Action.CHOICES super().__init__(*args, **kwargs) def to_representation(self, value): - return ActionFlag.value_to_choices(value) + return Action.value_to_choices(value) def to_internal_value(self, data): - return ActionFlag.choices_to_value(data) + if data is None: + return data + return Action.choices_to_value(data) -class ActionDisplayField(ActionField): +class ActionsDisplayField(ActionsField): def to_representation(self, value): values = super().to_representation(value) - choices = dict(ActionFlag.CHOICES) + choices = dict(Action.CHOICES) return [choices.get(i) for i in values] class AssetPermissionCreateUpdateSerializer(BulkOrgResourceModelSerializer): - actions = ActionField() + actions = ActionsField(required=False, allow_null=True) class Meta: model = AssetPermission @@ -47,7 +49,7 @@ class AssetPermissionListSerializer(BulkOrgResourceModelSerializer): assets = StringManyToManyField(many=True, read_only=True) nodes = StringManyToManyField(many=True, read_only=True) system_users = StringManyToManyField(many=True, read_only=True) - actions = ActionDisplayField() + actions = ActionsDisplayField() is_valid = serializers.BooleanField() is_expired = serializers.BooleanField() diff --git a/apps/perms/serializers/user_permission.py b/apps/perms/serializers/user_permission.py index 43cf47136..639ba7140 100644 --- a/apps/perms/serializers/user_permission.py +++ b/apps/perms/serializers/user_permission.py @@ -6,7 +6,7 @@ from rest_framework import serializers from assets.models import Node, SystemUser from assets.serializers import AssetSerializer -from .asset_permission import ActionField +from .asset_permission import ActionsField __all__ = [ 'AssetPermissionNodeSerializer', 'GrantedNodeSerializer', @@ -19,7 +19,7 @@ class AssetSystemUserSerializer(serializers.ModelSerializer): """ 查看授权的资产系统用户的数据结构,这个和AssetSerializer不同,字段少 """ - actions = ActionField(read_only=True) + actions = ActionsField(read_only=True) class Meta: model = SystemUser @@ -115,4 +115,4 @@ class GrantedNodeSerializer(serializers.ModelSerializer): class ActionsSerializer(serializers.Serializer): - actions = ActionField(read_only=True) \ No newline at end of file + actions = ActionsField(read_only=True) diff --git a/apps/perms/signals_handler.py b/apps/perms/signals_handler.py index a1813916d..e8f2eecbf 100644 --- a/apps/perms/signals_handler.py +++ b/apps/perms/signals_handler.py @@ -6,7 +6,7 @@ from django.db import transaction from common.utils import get_logger from .utils import AssetPermissionUtil -from .models import AssetPermission, Action +from .models import AssetPermission logger = get_logger(__file__) diff --git a/apps/perms/utils/asset_permission.py b/apps/perms/utils/asset_permission.py index fbf0e0d6b..4f2b8561f 100644 --- a/apps/perms/utils/asset_permission.py +++ b/apps/perms/utils/asset_permission.py @@ -17,7 +17,7 @@ from orgs.utils import set_to_root_org from common.utils import get_logger from common.tree import TreeNode from .. import const -from ..models import AssetPermission, Action, ActionFlag +from ..models import AssetPermission, Action from ..hands import Node, Asset from assets.utils import NodeUtil @@ -569,7 +569,7 @@ def parse_asset_to_tree_node(node, asset, system_users): 'protocol': system_user.protocol, 'priority': system_user.priority, 'login_mode': system_user.login_mode, - 'actions': [ActionFlag.value_to_choices(action)], + 'actions': [Action.value_to_choices(action)], }) data = { 'id': str(asset.id), diff --git a/apps/perms/views/asset_permission.py b/apps/perms/views/asset_permission.py index ca2d27e42..2981c9910 100644 --- a/apps/perms/views/asset_permission.py +++ b/apps/perms/views/asset_permission.py @@ -10,10 +10,9 @@ from django.conf import settings from common.permissions import PermissionsMixin, IsOrgAdmin from orgs.utils import current_org -from perms.hands import Node, Asset, SystemUser, User, UserGroup -from perms.models import AssetPermission, Action +from perms.hands import Node, Asset, SystemUser, UserGroup +from perms.models import AssetPermission from perms.forms import AssetPermissionForm -from perms.const import PERMS_ACTION_NAME_ALL __all__ = [ diff --git a/apps/settings/signals_handler.py b/apps/settings/signals_handler.py index 7a1b782f5..9302b63e2 100644 --- a/apps/settings/signals_handler.py +++ b/apps/settings/signals_handler.py @@ -77,6 +77,7 @@ def monkey_patch_settings(sender, **kwargs): @receiver(django_ready) def auto_generate_terminal_host_key(sender, **kwargs): try: + print("Auto gen host key") if Setting.objects.filter(name='TERMINAL_HOST_KEY').exists(): return private_key, public_key = ssh_key_gen()