mirror of
https://github.com/jumpserver/jumpserver.git
synced 2025-07-11 13:53:28 +00:00
Merge branch 'bugfix' of github.com:jumpserver/jumpserver into bugfix
This commit is contained in:
commit
bbf5e28571
@ -1,6 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.core.exceptions import ValidationError
|
||||||
|
import re
|
||||||
|
|
||||||
from orgs.mixins import OrgModelForm
|
from orgs.mixins import OrgModelForm
|
||||||
from ..models import CommandFilter, CommandFilterRule
|
from ..models import CommandFilter, CommandFilterRule
|
||||||
@ -15,6 +17,8 @@ class CommandFilterForm(OrgModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class CommandFilterRuleForm(OrgModelForm):
|
class CommandFilterRuleForm(OrgModelForm):
|
||||||
|
invalid_pattern = re.compile(r'[\.\*\+\[\\\?\{\}\^\$\|\(\)\#\<\>]')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CommandFilterRule
|
model = CommandFilterRule
|
||||||
fields = [
|
fields = [
|
||||||
@ -25,3 +29,11 @@ class CommandFilterRuleForm(OrgModelForm):
|
|||||||
'placeholder': 'eg:\r\nreboot\r\nrm -rf'
|
'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
|
||||||
|
@ -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'},
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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',
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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'),
|
|
||||||
),
|
|
||||||
]
|
|
@ -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),
|
|
||||||
]
|
|
@ -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')},
|
|
||||||
),
|
|
||||||
]
|
|
@ -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')},
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,6 +1,5 @@
|
|||||||
# Generated by Django 2.1.7 on 2019-06-24 13:08
|
# Generated by Django 2.1.7 on 2019-06-24 13:08
|
||||||
|
|
||||||
import common.fields.model
|
|
||||||
from django.db import migrations
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
|
import re
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from common.fields import ChoiceDisplayField
|
from common.fields import ChoiceDisplayField
|
||||||
@ -20,8 +21,16 @@ class CommandFilterSerializer(BulkOrgResourceModelSerializer):
|
|||||||
|
|
||||||
class CommandFilterRuleSerializer(BulkOrgResourceModelSerializer):
|
class CommandFilterRuleSerializer(BulkOrgResourceModelSerializer):
|
||||||
serializer_choice_field = ChoiceDisplayField
|
serializer_choice_field = ChoiceDisplayField
|
||||||
|
invalid_pattern = re.compile(r'[\.\*\+\[\\\?\{\}\^\$\|\(\)\#\<\>]')
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = CommandFilterRule
|
model = CommandFilterRule
|
||||||
fields = '__all__'
|
fields = '__all__'
|
||||||
list_serializer_class = AdaptedBulkListSerializer
|
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
|
||||||
|
@ -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
|
|
6
apps/common/mixins/__init__.py
Normal file
6
apps/common/mixins/__init__.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
from .models import *
|
||||||
|
from .serializers import *
|
||||||
|
from .api import *
|
||||||
|
from .views import *
|
84
apps/common/mixins/api.py
Normal file
84
apps/common/mixins/api.py
Normal file
@ -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
|
42
apps/common/mixins/models.py
Normal file
42
apps/common/mixins/models.py
Normal file
@ -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()
|
95
apps/common/mixins/serializers.py
Normal file
95
apps/common/mixins/serializers.py
Normal file
@ -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
|
40
apps/common/mixins/views.py
Normal file
40
apps/common/mixins/views.py
Normal file
@ -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)
|
||||||
|
|
||||||
|
|
@ -301,10 +301,10 @@ LOGGING = {
|
|||||||
'handlers': ['gunicorn_console', 'gunicorn_file'],
|
'handlers': ['gunicorn_console', 'gunicorn_file'],
|
||||||
'level': 'INFO',
|
'level': 'INFO',
|
||||||
},
|
},
|
||||||
# 'django.db': {
|
'django.db': {
|
||||||
# 'handlers': ['console', 'file'],
|
'handlers': ['console', 'file'],
|
||||||
# 'level': 'DEBUG'
|
'level': 'DEBUG'
|
||||||
# }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Jumpserver 0.3.3\n"
|
"Project-Id-Version: Jumpserver 0.3.3\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 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"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||||
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
|
"Language-Team: Jumpserver team<ibuler@qq.com>\n"
|
||||||
@ -86,7 +86,7 @@ msgstr "运行参数"
|
|||||||
#: assets/templates/assets/system_user_list.html:55 audits/models.py:19
|
#: 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:41
|
||||||
#: audits/templates/audits/ftp_log_list.html:71
|
#: 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_create_update.html:45
|
||||||
#: perms/templates/perms/asset_permission_list.html:48
|
#: perms/templates/perms/asset_permission_list.html:48
|
||||||
#: perms/templates/perms/asset_permission_list.html:117
|
#: 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
|
#: 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/models.py:20 audits/templates/audits/ftp_log_list.html:49
|
||||||
#: audits/templates/audits/ftp_log_list.html:72
|
#: audits/templates/audits/ftp_log_list.html:72
|
||||||
#: perms/forms/asset_permission.py:53 perms/models/asset_permission.py:55
|
#: perms/forms/asset_permission.py:74 perms/models/asset_permission.py:87
|
||||||
#: perms/models/asset_permission.py:76
|
#: perms/models/asset_permission.py:104
|
||||||
#: perms/templates/perms/asset_permission_detail.html:140
|
#: perms/templates/perms/asset_permission_detail.html:140
|
||||||
#: perms/templates/perms/asset_permission_list.html:50
|
#: perms/templates/perms/asset_permission_list.html:50
|
||||||
#: perms/templates/perms/asset_permission_list.html:71
|
#: 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_detail.html:58
|
||||||
#: assets/templates/assets/system_user_list.html:51 ops/models/adhoc.py:37
|
#: 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
|
#: 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/models/base.py:35
|
||||||
#: perms/templates/perms/asset_permission_detail.html:62
|
#: perms/templates/perms/asset_permission_detail.html:62
|
||||||
#: perms/templates/perms/asset_permission_list.html:45
|
#: perms/templates/perms/asset_permission_list.html:45
|
||||||
@ -215,10 +215,10 @@ msgstr "参数"
|
|||||||
#: assets/templates/assets/domain_detail.html:72
|
#: assets/templates/assets/domain_detail.html:72
|
||||||
#: assets/templates/assets/system_user_detail.html:100
|
#: assets/templates/assets/system_user_detail.html:100
|
||||||
#: ops/templates/ops/adhoc_detail.html:86 orgs/models.py:14
|
#: 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/asset_permission_detail.html:98
|
||||||
#: perms/templates/perms/remote_app_permission_detail.html:90
|
#: 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
|
#: users/templates/users/user_detail.html:111
|
||||||
#: xpack/plugins/change_auth_plan/models.py:106
|
#: xpack/plugins/change_auth_plan/models.py:106
|
||||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:113
|
#: 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/domain_detail.html:68
|
||||||
#: assets/templates/assets/system_user_detail.html:96
|
#: assets/templates/assets/system_user_detail.html:96
|
||||||
#: ops/templates/ops/adhoc_detail.html:90 ops/templates/ops/task_detail.html:64
|
#: 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/models/base.py:42
|
||||||
#: perms/templates/perms/asset_permission_detail.html:94
|
#: perms/templates/perms/asset_permission_detail.html:94
|
||||||
#: perms/templates/perms/remote_app_permission_detail.html:86
|
#: 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_detail.html:104
|
||||||
#: assets/templates/assets/system_user_list.html:59
|
#: assets/templates/assets/system_user_list.html:59
|
||||||
#: assets/templates/assets/user_asset_list.html:175 ops/models/adhoc.py:43
|
#: 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/models/base.py:43
|
||||||
#: perms/templates/perms/asset_permission_detail.html:102
|
#: perms/templates/perms/asset_permission_detail.html:102
|
||||||
#: perms/templates/perms/remote_app_permission_detail.html:94
|
#: 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:20
|
||||||
#: users/templates/users/user_group_list.html:70
|
#: users/templates/users/user_group_list.html:70
|
||||||
#: users/templates/users/user_list.html:20
|
#: 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_list.html:99
|
||||||
#: users/templates/users/user_profile.html:177
|
#: users/templates/users/user_profile.html:177
|
||||||
#: users/templates/users/user_profile.html:187
|
#: users/templates/users/user_profile.html:187
|
||||||
@ -481,7 +480,6 @@ msgstr "更新"
|
|||||||
#: users/templates/users/user_detail.html:30
|
#: users/templates/users/user_detail.html:30
|
||||||
#: users/templates/users/user_group_detail.html:32
|
#: users/templates/users/user_group_detail.html:32
|
||||||
#: users/templates/users/user_group_list.html:72
|
#: users/templates/users/user_group_list.html:72
|
||||||
#: users/templates/users/user_list.html:104
|
|
||||||
#: users/templates/users/user_list.html:108
|
#: 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_detail.html:33
|
||||||
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:57
|
#: 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
|
#: 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/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
|
#: 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/forms/asset_permission.py:21 perms/models/asset_permission.py:27
|
||||||
#: perms/models/asset_permission.py:57
|
|
||||||
#: perms/templates/perms/asset_permission_create_update.html:50
|
#: perms/templates/perms/asset_permission_create_update.html:50
|
||||||
#: perms/templates/perms/asset_permission_list.html:52
|
#: perms/templates/perms/asset_permission_list.html:52
|
||||||
#: perms/templates/perms/asset_permission_list.html:126
|
#: perms/templates/perms/asset_permission_list.html:126
|
||||||
@ -552,7 +549,7 @@ msgstr "动作"
|
|||||||
|
|
||||||
#: applications/templates/applications/user_remote_app_list.html:57
|
#: applications/templates/applications/user_remote_app_list.html:57
|
||||||
#: assets/templates/assets/user_asset_list.html:100 perms/const.py:19
|
#: 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"
|
msgid "Connect"
|
||||||
msgstr "连接"
|
msgstr "连接"
|
||||||
|
|
||||||
@ -591,11 +588,11 @@ msgstr "请选择需要更新的资产"
|
|||||||
msgid "You can't update the root node name"
|
msgid "You can't update the root node name"
|
||||||
msgstr "不能修改根节点名称"
|
msgstr "不能修改根节点名称"
|
||||||
|
|
||||||
#: assets/api/node.py:281
|
#: assets/api/node.py:283
|
||||||
msgid "Update node asset hardware information: {}"
|
msgid "Update node asset hardware information: {}"
|
||||||
msgstr "更新节点资产硬件信息: {}"
|
msgstr "更新节点资产硬件信息: {}"
|
||||||
|
|
||||||
#: assets/api/node.py:295
|
#: assets/api/node.py:297
|
||||||
msgid "Test if the assets under the node are connectable: {}"
|
msgid "Test if the assets under the node are connectable: {}"
|
||||||
msgstr "测试节点下资产是否可连接: {}"
|
msgstr "测试节点下资产是否可连接: {}"
|
||||||
|
|
||||||
@ -622,7 +619,7 @@ msgstr "未知"
|
|||||||
#: assets/templates/assets/asset_detail.html:194
|
#: assets/templates/assets/asset_detail.html:194
|
||||||
#: assets/templates/assets/asset_detail.html:202
|
#: assets/templates/assets/asset_detail.html:202
|
||||||
#: assets/templates/assets/system_user_assets.html:83
|
#: 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
|
#: xpack/plugins/change_auth_plan/models.py:72
|
||||||
msgid "Nodes"
|
msgid "Nodes"
|
||||||
msgstr "节点"
|
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:64 assets/forms/asset.py:86 assets/forms/asset.py:99
|
||||||
#: assets/forms/asset.py:134 assets/models/node.py:248
|
#: assets/forms/asset.py:134 assets/models/node.py:248
|
||||||
#: assets/templates/assets/asset_create.html:42
|
#: assets/templates/assets/asset_create.html:42
|
||||||
#: perms/forms/asset_permission.py:50 perms/forms/asset_permission.py:60
|
#: perms/forms/asset_permission.py:71 perms/forms/asset_permission.py:79
|
||||||
#: perms/models/asset_permission.py:74
|
#: perms/models/asset_permission.py:102
|
||||||
#: perms/templates/perms/asset_permission_list.html:49
|
#: perms/templates/perms/asset_permission_list.html:49
|
||||||
#: perms/templates/perms/asset_permission_list.html:70
|
#: perms/templates/perms/asset_permission_list.html:70
|
||||||
#: perms/templates/perms/asset_permission_list.html:120
|
#: perms/templates/perms/asset_permission_list.html:120
|
||||||
@ -695,6 +692,10 @@ msgstr "如果有多个的互相隔离的网络,设置资产属于的网域,
|
|||||||
msgid "Select assets"
|
msgid "Select assets"
|
||||||
msgstr "选择资产"
|
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
|
#: assets/forms/domain.py:51
|
||||||
msgid "Password should not contain special characters"
|
msgid "Password should not contain special characters"
|
||||||
msgstr "不能包含特殊字符"
|
msgstr "不能包含特殊字符"
|
||||||
@ -1000,7 +1001,7 @@ msgid "Operator"
|
|||||||
msgstr "运营商"
|
msgstr "运营商"
|
||||||
|
|
||||||
#: assets/models/cluster.py:36 assets/models/group.py:34
|
#: assets/models/cluster.py:36 assets/models/group.py:34
|
||||||
#: perms/utils/asset_permission.py:67
|
#: perms/utils/asset_permission.py:106
|
||||||
msgid "Default"
|
msgid "Default"
|
||||||
msgstr "默认"
|
msgstr "默认"
|
||||||
|
|
||||||
@ -1112,7 +1113,7 @@ msgstr "默认资产组"
|
|||||||
#: audits/templates/audits/password_change_log_list.html:50
|
#: audits/templates/audits/password_change_log_list.html:50
|
||||||
#: ops/templates/ops/command_execution_list.html:35
|
#: ops/templates/ops/command_execution_list.html:35
|
||||||
#: ops/templates/ops/command_execution_list.html:60
|
#: 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/models/base.py:36
|
||||||
#: perms/templates/perms/asset_permission_create_update.html:41
|
#: perms/templates/perms/asset_permission_create_update.html:41
|
||||||
#: perms/templates/perms/asset_permission_list.html:46
|
#: perms/templates/perms/asset_permission_list.html:46
|
||||||
@ -1124,9 +1125,9 @@ msgstr "默认资产组"
|
|||||||
#: terminal/templates/terminal/command_list.html:72
|
#: terminal/templates/terminal/command_list.html:72
|
||||||
#: terminal/templates/terminal/session_list.html:33
|
#: terminal/templates/terminal/session_list.html:33
|
||||||
#: terminal/templates/terminal/session_list.html:71 users/forms.py:301
|
#: 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_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/forms.py:26
|
||||||
#: xpack/plugins/orgs/templates/orgs/org_detail.html:113
|
#: xpack/plugins/orgs/templates/orgs/org_detail.html:113
|
||||||
#: xpack/plugins/orgs/templates/orgs/org_list.html:14
|
#: xpack/plugins/orgs/templates/orgs/org_list.html:14
|
||||||
@ -1205,26 +1206,25 @@ msgstr "登录模式"
|
|||||||
msgid "%(value)s is not an even number"
|
msgid "%(value)s is not an even number"
|
||||||
msgstr "%(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/serializers/asset_user.py:30 assets/serializers/system_user.py:30
|
||||||
#: assets/templates/assets/_asset_user_list.html:18
|
#: assets/templates/assets/_asset_user_list.html:18
|
||||||
msgid "Connectivity"
|
msgid "Connectivity"
|
||||||
msgstr "连接"
|
msgstr "连接"
|
||||||
|
|
||||||
#: assets/serializers/asset.py:45 assets/serializers/asset.py:155
|
#: assets/serializers/asset.py:44 assets/templates/assets/asset_create.html:24
|
||||||
#: assets/templates/assets/asset_create.html:24
|
|
||||||
msgid "Protocols"
|
msgid "Protocols"
|
||||||
msgstr "协议组"
|
msgstr "协议组"
|
||||||
|
|
||||||
#: assets/serializers/asset.py:73
|
#: assets/serializers/asset.py:72
|
||||||
msgid "Hardware info"
|
msgid "Hardware info"
|
||||||
msgstr "硬件信息"
|
msgstr "硬件信息"
|
||||||
|
|
||||||
#: assets/serializers/asset.py:74 orgs/mixins.py:192
|
#: assets/serializers/asset.py:73 orgs/mixins.py:192
|
||||||
msgid "Org name"
|
msgid "Org name"
|
||||||
msgstr "组织名称"
|
msgstr "组织名称"
|
||||||
|
|
||||||
#: assets/serializers/asset.py:92
|
#: assets/serializers/asset.py:91
|
||||||
msgid "Protocol duplicate: {}"
|
msgid "Protocol duplicate: {}"
|
||||||
msgstr "协议重复: {}"
|
msgstr "协议重复: {}"
|
||||||
|
|
||||||
@ -1710,7 +1710,7 @@ msgstr "创建日期"
|
|||||||
|
|
||||||
#: assets/templates/assets/asset_detail.html:154
|
#: assets/templates/assets/asset_detail.html:154
|
||||||
#: assets/templates/assets/user_asset_list.html:46
|
#: 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_create_update.html:55
|
||||||
#: perms/templates/perms/asset_permission_detail.html:120
|
#: perms/templates/perms/asset_permission_detail.html:120
|
||||||
#: perms/templates/perms/remote_app_permission_create_update.html:54
|
#: perms/templates/perms/remote_app_permission_create_update.html:54
|
||||||
@ -2056,10 +2056,6 @@ msgstr "批量更新资产"
|
|||||||
msgid "Update asset"
|
msgid "Update asset"
|
||||||
msgstr "更新资产"
|
msgstr "更新资产"
|
||||||
|
|
||||||
#: assets/views/asset.py:347
|
|
||||||
msgid "already exists"
|
|
||||||
msgstr "已经存在"
|
|
||||||
|
|
||||||
#: assets/views/cmd_filter.py:32
|
#: assets/views/cmd_filter.py:32
|
||||||
msgid "Command filter list"
|
msgid "Command filter list"
|
||||||
msgstr "命令过滤器列表"
|
msgstr "命令过滤器列表"
|
||||||
@ -2557,8 +2553,8 @@ msgstr "欢迎回来,请输入用户名和密码登录"
|
|||||||
msgid "Please enable cookies and try again."
|
msgid "Please enable cookies and try again."
|
||||||
msgstr "设置你的浏览器支持cookie"
|
msgstr "设置你的浏览器支持cookie"
|
||||||
|
|
||||||
#: authentication/views/login.py:172 users/views/user.py:555
|
#: authentication/views/login.py:172 users/views/user.py:412
|
||||||
#: users/views/user.py:580
|
#: users/views/user.py:437
|
||||||
msgid "MFA code invalid, or ntp sync server time"
|
msgid "MFA code invalid, or ntp sync server time"
|
||||||
msgstr "MFA验证码不正确,或者服务器端时间不对"
|
msgstr "MFA验证码不正确,或者服务器端时间不对"
|
||||||
|
|
||||||
@ -3000,11 +2996,11 @@ msgstr "命令执行"
|
|||||||
msgid "Organization"
|
msgid "Organization"
|
||||||
msgstr "组织"
|
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"
|
msgid "All"
|
||||||
msgstr "全部"
|
msgstr "全部"
|
||||||
|
|
||||||
#: perms/const.py:20 perms/models/asset_permission.py:46
|
#: perms/const.py:20 perms/models/asset_permission.py:47
|
||||||
msgid "Upload file"
|
msgid "Upload file"
|
||||||
msgstr "上传文件"
|
msgstr "上传文件"
|
||||||
|
|
||||||
@ -3012,8 +3008,8 @@ msgstr "上传文件"
|
|||||||
msgid "Download file"
|
msgid "Download file"
|
||||||
msgstr "下载文件"
|
msgstr "下载文件"
|
||||||
|
|
||||||
#: perms/forms/asset_permission.py:44 perms/forms/remote_app_permission.py:34
|
#: perms/forms/asset_permission.py:65 perms/forms/remote_app_permission.py:34
|
||||||
#: perms/models/asset_permission.py:75 perms/models/base.py:37
|
#: 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:47
|
||||||
#: perms/templates/perms/asset_permission_list.html:67
|
#: perms/templates/perms/asset_permission_list.html:67
|
||||||
#: perms/templates/perms/asset_permission_list.html:114
|
#: perms/templates/perms/asset_permission_list.html:114
|
||||||
@ -3026,30 +3022,34 @@ msgstr "下载文件"
|
|||||||
msgid "User group"
|
msgid "User group"
|
||||||
msgstr "用户组"
|
msgstr "用户组"
|
||||||
|
|
||||||
#: perms/forms/asset_permission.py:63
|
#: perms/forms/asset_permission.py:82
|
||||||
msgid ""
|
msgid ""
|
||||||
"Tips: The RDP protocol does not support separate controls for uploading or "
|
"Tips: The RDP protocol does not support separate controls for uploading or "
|
||||||
"downloading files"
|
"downloading files"
|
||||||
msgstr "提示:RDP 协议不支持单独控制上传或下载文件"
|
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"
|
msgid "User or group at least one required"
|
||||||
msgstr "用户和用户组至少选一个"
|
msgstr "用户和用户组至少选一个"
|
||||||
|
|
||||||
#: perms/forms/asset_permission.py:82
|
#: perms/forms/asset_permission.py:101
|
||||||
msgid "Asset or group at least one required"
|
msgid "Asset or group at least one required"
|
||||||
msgstr "资产和节点至少选一个"
|
msgstr "资产和节点至少选一个"
|
||||||
|
|
||||||
#: perms/models/asset_permission.py:47
|
#: perms/models/asset_permission.py:49
|
||||||
msgid "Upload download"
|
msgid "Upload download"
|
||||||
msgstr "上传下载"
|
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
|
#: templates/_nav.html:44
|
||||||
msgid "Asset permission"
|
msgid "Asset permission"
|
||||||
msgstr "资产授权"
|
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/asset_permission_detail.html:90
|
||||||
#: perms/templates/perms/remote_app_permission_detail.html:82
|
#: perms/templates/perms/remote_app_permission_detail.html:82
|
||||||
#: users/models/user.py:102 users/templates/users/user_detail.html:107
|
#: users/models/user.py:102 users/templates/users/user_detail.html:107
|
||||||
@ -3199,8 +3199,8 @@ msgid "Add user group to this permission"
|
|||||||
msgstr "添加用户组"
|
msgstr "添加用户组"
|
||||||
|
|
||||||
#: perms/views/asset_permission.py:34 perms/views/asset_permission.py:65
|
#: 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:82 perms/views/asset_permission.py:99
|
||||||
#: perms/views/asset_permission.py:134 perms/views/asset_permission.py:167
|
#: 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:33
|
||||||
#: perms/views/remote_app_permission.py:49
|
#: perms/views/remote_app_permission.py:49
|
||||||
#: perms/views/remote_app_permission.py:65
|
#: perms/views/remote_app_permission.py:65
|
||||||
@ -3219,19 +3219,19 @@ msgstr "资产授权列表"
|
|||||||
msgid "Create asset permission"
|
msgid "Create asset permission"
|
||||||
msgstr "创建权限规则"
|
msgstr "创建权限规则"
|
||||||
|
|
||||||
#: perms/views/asset_permission.py:82
|
#: perms/views/asset_permission.py:83
|
||||||
msgid "Update asset permission"
|
msgid "Update asset permission"
|
||||||
msgstr "更新资产授权"
|
msgstr "更新资产授权"
|
||||||
|
|
||||||
#: perms/views/asset_permission.py:98
|
#: perms/views/asset_permission.py:100
|
||||||
msgid "Asset permission detail"
|
msgid "Asset permission detail"
|
||||||
msgstr "资产授权详情"
|
msgstr "资产授权详情"
|
||||||
|
|
||||||
#: perms/views/asset_permission.py:135
|
#: perms/views/asset_permission.py:137
|
||||||
msgid "Asset permission user list"
|
msgid "Asset permission user list"
|
||||||
msgstr "资产授权用户列表"
|
msgstr "资产授权用户列表"
|
||||||
|
|
||||||
#: perms/views/asset_permission.py:168
|
#: perms/views/asset_permission.py:170
|
||||||
msgid "Asset permission asset list"
|
msgid "Asset permission asset list"
|
||||||
msgstr "资产授权资产列表"
|
msgstr "资产授权资产列表"
|
||||||
|
|
||||||
@ -3828,7 +3828,7 @@ msgstr "商业支持"
|
|||||||
#: users/templates/users/user_profile.html:17
|
#: users/templates/users/user_profile.html:17
|
||||||
#: users/templates/users/user_profile_update.html:37
|
#: users/templates/users/user_profile_update.html:37
|
||||||
#: users/templates/users/user_profile_update.html:57
|
#: 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"
|
msgid "Profile"
|
||||||
msgstr "个人信息"
|
msgstr "个人信息"
|
||||||
|
|
||||||
@ -3923,13 +3923,13 @@ msgstr ""
|
|||||||
|
|
||||||
#: templates/_nav.html:10 users/views/group.py:28 users/views/group.py:45
|
#: 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/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/login.py:154 users/views/user.py:68 users/views/user.py:85
|
||||||
#: users/views/user.py:131 users/views/user.py:211 users/views/user.py:374
|
#: users/views/user.py:129 users/views/user.py:209 users/views/user.py:231
|
||||||
#: users/views/user.py:426 users/views/user.py:467
|
#: users/views/user.py:283 users/views/user.py:324
|
||||||
msgid "Users"
|
msgid "Users"
|
||||||
msgstr "用户管理"
|
msgstr "用户管理"
|
||||||
|
|
||||||
#: templates/_nav.html:13 users/views/user.py:71
|
#: templates/_nav.html:13 users/views/user.py:69
|
||||||
msgid "User list"
|
msgid "User list"
|
||||||
msgstr "用户列表"
|
msgstr "用户列表"
|
||||||
|
|
||||||
@ -4369,11 +4369,11 @@ msgid ""
|
|||||||
"You should use your ssh client tools connect terminal: {} <br /> <br />{}"
|
"You should use your ssh client tools connect terminal: {} <br /> <br />{}"
|
||||||
msgstr "你可以使用ssh客户端工具连接终端"
|
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."
|
msgid "You do not have permission."
|
||||||
msgstr "你没有权限"
|
msgstr "你没有权限"
|
||||||
|
|
||||||
#: users/api/user.py:221
|
#: users/api/user.py:186
|
||||||
msgid "Could not reset self otp, use profile reset instead"
|
msgid "Could not reset self otp, use profile reset instead"
|
||||||
msgstr "不能再该页面重置MFA, 请去个人信息页面重置"
|
msgstr "不能再该页面重置MFA, 请去个人信息页面重置"
|
||||||
|
|
||||||
@ -4405,7 +4405,7 @@ msgstr "添加到用户组"
|
|||||||
msgid "Public key should not be the same as your old one."
|
msgid "Public key should not be the same as your old one."
|
||||||
msgstr "不能和原来的密钥相同"
|
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"
|
msgid "Not a valid ssh public key"
|
||||||
msgstr "ssh密钥不合法"
|
msgstr "ssh密钥不合法"
|
||||||
|
|
||||||
@ -4532,7 +4532,7 @@ msgid "Date password last updated"
|
|||||||
msgstr "最后更新密码日期"
|
msgstr "最后更新密码日期"
|
||||||
|
|
||||||
#: users/models/user.py:139 users/templates/users/user_update.html:22
|
#: 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"
|
msgid "User auth from {}, go there change password"
|
||||||
msgstr "用户认证源来自 {}, 请去相应系统修改密码"
|
msgstr "用户认证源来自 {}, 请去相应系统修改密码"
|
||||||
|
|
||||||
@ -4569,10 +4569,12 @@ msgid "Avatar url"
|
|||||||
msgstr "头像路径"
|
msgstr "头像路径"
|
||||||
|
|
||||||
#: users/serializers/v1.py:46
|
#: users/serializers/v1.py:46
|
||||||
#, fuzzy
|
msgid "Role limit to {}"
|
||||||
#| msgid "Password does not match"
|
msgstr "角色只能为 {}"
|
||||||
|
|
||||||
|
#: users/serializers/v1.py:54
|
||||||
msgid "Password does not match security rules"
|
msgid "Password does not match security rules"
|
||||||
msgstr "密码不一致"
|
msgstr "密码不满足安全规则"
|
||||||
|
|
||||||
#: users/serializers_v2/user.py:36
|
#: users/serializers_v2/user.py:36
|
||||||
msgid "name not unique"
|
msgid "name not unique"
|
||||||
@ -4624,7 +4626,7 @@ msgid "Import users"
|
|||||||
msgstr "导入用户"
|
msgstr "导入用户"
|
||||||
|
|
||||||
#: users/templates/users/_user_update_modal.html:4
|
#: 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"
|
msgid "Update user"
|
||||||
msgstr "更新用户"
|
msgstr "更新用户"
|
||||||
|
|
||||||
@ -4762,12 +4764,12 @@ msgid "Very strong"
|
|||||||
msgstr "很强"
|
msgstr "很强"
|
||||||
|
|
||||||
#: users/templates/users/user_create.html:4
|
#: 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"
|
msgid "Create user"
|
||||||
msgstr "创建用户"
|
msgstr "创建用户"
|
||||||
|
|
||||||
#: users/templates/users/user_detail.html:19
|
#: 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"
|
msgid "User detail"
|
||||||
msgstr "用户详情"
|
msgstr "用户详情"
|
||||||
|
|
||||||
@ -4967,8 +4969,7 @@ msgstr "安装完成后点击下一步进入绑定页面(如已安装,直接
|
|||||||
msgid "Administrator Settings force MFA login"
|
msgid "Administrator Settings force MFA login"
|
||||||
msgstr "管理员设置强制使用MFA登录"
|
msgstr "管理员设置强制使用MFA登录"
|
||||||
|
|
||||||
#: users/templates/users/user_profile.html:120 users/views/user.py:248
|
#: users/templates/users/user_profile.html:120
|
||||||
#: users/views/user.py:303
|
|
||||||
msgid "User groups"
|
msgid "User groups"
|
||||||
msgstr "用户组"
|
msgstr "用户组"
|
||||||
|
|
||||||
@ -5243,7 +5244,7 @@ msgstr "Token错误或失效"
|
|||||||
msgid "Password not same"
|
msgid "Password not same"
|
||||||
msgstr "密码不一致"
|
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"
|
msgid "* Your password does not meet the requirements"
|
||||||
msgstr "* 您的密码不符合要求"
|
msgstr "* 您的密码不符合要求"
|
||||||
|
|
||||||
@ -5251,51 +5252,47 @@ msgstr "* 您的密码不符合要求"
|
|||||||
msgid "First login"
|
msgid "First login"
|
||||||
msgstr "首次登录"
|
msgstr "首次登录"
|
||||||
|
|
||||||
#: users/views/user.py:163
|
#: users/views/user.py:161
|
||||||
msgid "Bulk update user success"
|
msgid "Bulk update user success"
|
||||||
msgstr "批量更新用户成功"
|
msgstr "批量更新用户成功"
|
||||||
|
|
||||||
#: users/views/user.py:191
|
#: users/views/user.py:189
|
||||||
msgid "Bulk update user"
|
msgid "Bulk update user"
|
||||||
msgstr "批量更新用户"
|
msgstr "批量更新用户"
|
||||||
|
|
||||||
#: users/views/user.py:278
|
#: users/views/user.py:232
|
||||||
msgid "Invalid file."
|
|
||||||
msgstr "文件不合法"
|
|
||||||
|
|
||||||
#: users/views/user.py:375
|
|
||||||
msgid "User granted assets"
|
msgid "User granted assets"
|
||||||
msgstr "用户授权资产"
|
msgstr "用户授权资产"
|
||||||
|
|
||||||
#: users/views/user.py:408
|
#: users/views/user.py:265
|
||||||
msgid "Profile setting"
|
msgid "Profile setting"
|
||||||
msgstr "个人信息设置"
|
msgstr "个人信息设置"
|
||||||
|
|
||||||
#: users/views/user.py:427
|
#: users/views/user.py:284
|
||||||
msgid "Password update"
|
msgid "Password update"
|
||||||
msgstr "密码更新"
|
msgstr "密码更新"
|
||||||
|
|
||||||
#: users/views/user.py:468
|
#: users/views/user.py:325
|
||||||
msgid "Public key update"
|
msgid "Public key update"
|
||||||
msgstr "密钥更新"
|
msgstr "密钥更新"
|
||||||
|
|
||||||
#: users/views/user.py:510
|
#: users/views/user.py:367
|
||||||
msgid "Password invalid"
|
msgid "Password invalid"
|
||||||
msgstr "用户名或密码无效"
|
msgstr "用户名或密码无效"
|
||||||
|
|
||||||
#: users/views/user.py:610
|
#: users/views/user.py:467
|
||||||
msgid "MFA enable success"
|
msgid "MFA enable success"
|
||||||
msgstr "MFA 绑定成功"
|
msgstr "MFA 绑定成功"
|
||||||
|
|
||||||
#: users/views/user.py:611
|
#: users/views/user.py:468
|
||||||
msgid "MFA enable success, return login page"
|
msgid "MFA enable success, return login page"
|
||||||
msgstr "MFA 绑定成功,返回到登录页面"
|
msgstr "MFA 绑定成功,返回到登录页面"
|
||||||
|
|
||||||
#: users/views/user.py:613
|
#: users/views/user.py:470
|
||||||
msgid "MFA disable success"
|
msgid "MFA disable success"
|
||||||
msgstr "MFA 解绑成功"
|
msgstr "MFA 解绑成功"
|
||||||
|
|
||||||
#: users/views/user.py:614
|
#: users/views/user.py:471
|
||||||
msgid "MFA disable success, return login page"
|
msgid "MFA disable success, return login page"
|
||||||
msgstr "MFA 解绑成功,返回登录页面"
|
msgstr "MFA 解绑成功,返回登录页面"
|
||||||
|
|
||||||
@ -5783,10 +5780,8 @@ msgid "Restore default failed."
|
|||||||
msgstr "恢复默认失败!"
|
msgstr "恢复默认失败!"
|
||||||
|
|
||||||
#: xpack/plugins/interface/views.py:24
|
#: xpack/plugins/interface/views.py:24
|
||||||
#, fuzzy
|
|
||||||
#| msgid "Interval"
|
|
||||||
msgid "Interface"
|
msgid "Interface"
|
||||||
msgstr "间隔"
|
msgstr "界面"
|
||||||
|
|
||||||
#: xpack/plugins/interface/views.py:51
|
#: xpack/plugins/interface/views.py:51
|
||||||
msgid "It is already in the default setting state!"
|
msgid "It is already in the default setting state!"
|
||||||
@ -5946,6 +5941,12 @@ msgstr "密码匣子"
|
|||||||
msgid "vault create"
|
msgid "vault create"
|
||||||
msgstr "创建"
|
msgstr "创建"
|
||||||
|
|
||||||
|
#~ msgid "already exists"
|
||||||
|
#~ msgstr "已经存在"
|
||||||
|
|
||||||
|
#~ msgid "Invalid file."
|
||||||
|
#~ msgstr "文件不合法"
|
||||||
|
|
||||||
#~ msgid "Refresh all node assets amount"
|
#~ msgid "Refresh all node assets amount"
|
||||||
#~ msgstr "刷新所有节点资产数量"
|
#~ msgstr "刷新所有节点资产数量"
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ from rest_framework.pagination import LimitOffsetPagination
|
|||||||
|
|
||||||
from common.permissions import IsOrgAdmin
|
from common.permissions import IsOrgAdmin
|
||||||
from common.utils import get_object_or_none
|
from common.utils import get_object_or_none
|
||||||
from ..models import AssetPermission, Action
|
from ..models import AssetPermission
|
||||||
from ..hands import (
|
from ..hands import (
|
||||||
User, UserGroup, Asset, Node, SystemUser,
|
User, UserGroup, Asset, Node, SystemUser,
|
||||||
)
|
)
|
||||||
|
@ -21,7 +21,7 @@ from ..utils import (
|
|||||||
from ..hands import User, Asset, Node, SystemUser, NodeSerializer
|
from ..hands import User, Asset, Node, SystemUser, NodeSerializer
|
||||||
from .. import serializers, const
|
from .. import serializers, const
|
||||||
from ..mixins import AssetsFilterMixin
|
from ..mixins import AssetsFilterMixin
|
||||||
from ..models import ActionFlag
|
from ..models import Action
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
@ -423,7 +423,7 @@ class ValidateUserAssetPermissionApi(UserPermissionCacheMixin, APIView):
|
|||||||
return Response({'msg': False}, status=403)
|
return Response({'msg': False}, status=403)
|
||||||
|
|
||||||
action = granted_system_users[su]
|
action = granted_system_users[su]
|
||||||
choices = ActionFlag.value_to_choices(action)
|
choices = Action.value_to_choices(action)
|
||||||
if action_name not in choices:
|
if action_name not in choices:
|
||||||
return Response({'msg': False}, status=403)
|
return Response({'msg': False}, status=403)
|
||||||
|
|
||||||
|
@ -1,24 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
UNGROUPED_NODE_ID = "00000000-0000-0000-0000-000000000002"
|
||||||
|
|
||||||
__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"
|
|
||||||
|
@ -7,7 +7,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||||||
from orgs.mixins import OrgModelForm
|
from orgs.mixins import OrgModelForm
|
||||||
from orgs.utils import current_org
|
from orgs.utils import current_org
|
||||||
from assets.models import Asset, Node
|
from assets.models import Asset, Node
|
||||||
from ..models import AssetPermission, ActionFlag
|
from ..models import AssetPermission, Action
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'AssetPermissionForm',
|
'AssetPermissionForm',
|
||||||
@ -16,20 +16,20 @@ __all__ = [
|
|||||||
|
|
||||||
class ActionField(forms.MultipleChoiceField):
|
class ActionField(forms.MultipleChoiceField):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs['choices'] = ActionFlag.CHOICES
|
kwargs['choices'] = Action.CHOICES
|
||||||
kwargs['initial'] = ActionFlag.ALL
|
kwargs['initial'] = Action.ALL
|
||||||
kwargs['label'] = _("Action")
|
kwargs['label'] = _("Action")
|
||||||
kwargs['widget'] = forms.CheckboxSelectMultiple()
|
kwargs['widget'] = forms.CheckboxSelectMultiple()
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def to_python(self, value):
|
def to_python(self, value):
|
||||||
value = super().to_python(value)
|
value = super().to_python(value)
|
||||||
return ActionFlag.choices_to_value(value)
|
return Action.choices_to_value(value)
|
||||||
|
|
||||||
def prepare_value(self, value):
|
def prepare_value(self, value):
|
||||||
if value is None:
|
if value is None:
|
||||||
return value
|
return value
|
||||||
value = ActionFlag.value_to_choices(value)
|
value = Action.value_to_choices(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
@ -4,14 +4,6 @@ from django.db import migrations, models
|
|||||||
import uuid
|
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):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
@ -29,5 +21,4 @@ class Migration(migrations.Migration):
|
|||||||
'verbose_name': 'Action',
|
'verbose_name': 'Action',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.RunPython(add_default_actions)
|
|
||||||
]
|
]
|
||||||
|
@ -3,18 +3,6 @@
|
|||||||
from django.db import migrations, models
|
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):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
@ -27,5 +15,4 @@ class Migration(migrations.Migration):
|
|||||||
name='actions',
|
name='actions',
|
||||||
field=models.ManyToManyField(blank=True, related_name='permissions', to='perms.Action', verbose_name='Action'),
|
field=models.ManyToManyField(blank=True, related_name='permissions', to='perms.Action', verbose_name='Action'),
|
||||||
),
|
),
|
||||||
migrations.RunPython(set_default_action_to_existing_perms)
|
|
||||||
]
|
]
|
||||||
|
@ -6,21 +6,22 @@ from functools import reduce
|
|||||||
|
|
||||||
def migrate_old_actions(apps, schema_editor):
|
def migrate_old_actions(apps, schema_editor):
|
||||||
from orgs.utils import set_to_root_org
|
from orgs.utils import set_to_root_org
|
||||||
from ..models import ActionFlag
|
|
||||||
set_to_root_org()
|
set_to_root_org()
|
||||||
perm_model = apps.get_model('perms', 'AssetPermission')
|
perm_model = apps.get_model('perms', 'AssetPermission')
|
||||||
db_alias = schema_editor.connection.alias
|
db_alias = schema_editor.connection.alias
|
||||||
perms = perm_model.objects.using(db_alias).all()
|
perms = perm_model.objects.using(db_alias).all()
|
||||||
actions_map = {
|
actions_map = {
|
||||||
"all": ActionFlag.ALL,
|
"all": 0b11111111,
|
||||||
"connect": ActionFlag.CONNECT,
|
"connect": 0b00000001,
|
||||||
"upload_file": ActionFlag.UPLOAD,
|
"upload_file": 0b00000010,
|
||||||
"download_file": ActionFlag.DOWNLOAD,
|
"download_file": 0b00000100,
|
||||||
}
|
}
|
||||||
|
|
||||||
for perm in perms:
|
for perm in perms:
|
||||||
actions = perm.actions.all()
|
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)
|
new_action = reduce(lambda x, y: x | y, new_actions)
|
||||||
perm.action = new_action
|
perm.action = new_action
|
||||||
perm.save()
|
perm.save()
|
||||||
|
@ -19,4 +19,5 @@ class Migration(migrations.Migration):
|
|||||||
old_name='action',
|
old_name='action',
|
||||||
new_name='actions',
|
new_name='actions',
|
||||||
),
|
),
|
||||||
|
migrations.DeleteModel(name='Action'),
|
||||||
]
|
]
|
||||||
|
@ -4,37 +4,18 @@ from functools import reduce
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from common.utils import date_expired_default, set_or_append_attr_bulk
|
from common.utils import date_expired_default
|
||||||
from orgs.mixins import OrgModelMixin
|
from orgs.mixins import OrgModelMixin
|
||||||
|
|
||||||
from ..const import PERMS_ACTION_NAME_CHOICES, PERMS_ACTION_NAME_ALL
|
|
||||||
from .base import BasePermission
|
from .base import BasePermission
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'Action', 'AssetPermission', 'NodePermission', 'ActionFlag'
|
'AssetPermission', 'NodePermission', 'Action',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class Action(models.Model):
|
class Action:
|
||||||
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:
|
|
||||||
CONNECT = 0b00000001
|
CONNECT = 0b00000001
|
||||||
UPLOAD = 0b00000010
|
UPLOAD = 0b00000010
|
||||||
DOWNLOAD = 0b00000100
|
DOWNLOAD = 0b00000100
|
||||||
@ -74,6 +55,8 @@ class ActionFlag:
|
|||||||
x = cls.NAME_MAP_REVERSE.get(x, 0)
|
x = cls.NAME_MAP_REVERSE.get(x, 0)
|
||||||
y = cls.NAME_MAP_REVERSE.get(y, 0)
|
y = cls.NAME_MAP_REVERSE.get(y, 0)
|
||||||
return x | y
|
return x | y
|
||||||
|
if not value:
|
||||||
|
return None
|
||||||
return reduce(to_choices, value)
|
return reduce(to_choices, value)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -86,7 +69,7 @@ class AssetPermission(BasePermission):
|
|||||||
nodes = models.ManyToManyField('assets.Node', related_name='granted_by_permissions', blank=True, verbose_name=_("Nodes"))
|
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"))
|
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.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:
|
class Meta:
|
||||||
unique_together = [('org_id', 'name')]
|
unique_together = [('org_id', 'name')]
|
||||||
|
@ -5,36 +5,38 @@ from rest_framework import serializers
|
|||||||
|
|
||||||
from common.fields import StringManyToManyField
|
from common.fields import StringManyToManyField
|
||||||
from orgs.mixins import BulkOrgResourceModelSerializer
|
from orgs.mixins import BulkOrgResourceModelSerializer
|
||||||
from perms.models import AssetPermission, ActionFlag
|
from perms.models import AssetPermission, Action
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'AssetPermissionCreateUpdateSerializer', 'AssetPermissionListSerializer',
|
'AssetPermissionCreateUpdateSerializer', 'AssetPermissionListSerializer',
|
||||||
'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer',
|
'AssetPermissionUpdateUserSerializer', 'AssetPermissionUpdateAssetSerializer',
|
||||||
'ActionField',
|
'ActionsField',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class ActionField(serializers.MultipleChoiceField):
|
class ActionsField(serializers.MultipleChoiceField):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
kwargs['choices'] = ActionFlag.CHOICES
|
kwargs['choices'] = Action.CHOICES
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def to_representation(self, value):
|
def to_representation(self, value):
|
||||||
return ActionFlag.value_to_choices(value)
|
return Action.value_to_choices(value)
|
||||||
|
|
||||||
def to_internal_value(self, data):
|
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):
|
def to_representation(self, value):
|
||||||
values = super().to_representation(value)
|
values = super().to_representation(value)
|
||||||
choices = dict(ActionFlag.CHOICES)
|
choices = dict(Action.CHOICES)
|
||||||
return [choices.get(i) for i in values]
|
return [choices.get(i) for i in values]
|
||||||
|
|
||||||
|
|
||||||
class AssetPermissionCreateUpdateSerializer(BulkOrgResourceModelSerializer):
|
class AssetPermissionCreateUpdateSerializer(BulkOrgResourceModelSerializer):
|
||||||
actions = ActionField()
|
actions = ActionsField(required=False, allow_null=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = AssetPermission
|
model = AssetPermission
|
||||||
@ -47,7 +49,7 @@ class AssetPermissionListSerializer(BulkOrgResourceModelSerializer):
|
|||||||
assets = StringManyToManyField(many=True, read_only=True)
|
assets = StringManyToManyField(many=True, read_only=True)
|
||||||
nodes = StringManyToManyField(many=True, read_only=True)
|
nodes = StringManyToManyField(many=True, read_only=True)
|
||||||
system_users = StringManyToManyField(many=True, read_only=True)
|
system_users = StringManyToManyField(many=True, read_only=True)
|
||||||
actions = ActionDisplayField()
|
actions = ActionsDisplayField()
|
||||||
is_valid = serializers.BooleanField()
|
is_valid = serializers.BooleanField()
|
||||||
is_expired = serializers.BooleanField()
|
is_expired = serializers.BooleanField()
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ from rest_framework import serializers
|
|||||||
from assets.models import Node, SystemUser
|
from assets.models import Node, SystemUser
|
||||||
from assets.serializers import AssetSerializer
|
from assets.serializers import AssetSerializer
|
||||||
|
|
||||||
from .asset_permission import ActionField
|
from .asset_permission import ActionsField
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'AssetPermissionNodeSerializer', 'GrantedNodeSerializer',
|
'AssetPermissionNodeSerializer', 'GrantedNodeSerializer',
|
||||||
@ -19,7 +19,7 @@ class AssetSystemUserSerializer(serializers.ModelSerializer):
|
|||||||
"""
|
"""
|
||||||
查看授权的资产系统用户的数据结构,这个和AssetSerializer不同,字段少
|
查看授权的资产系统用户的数据结构,这个和AssetSerializer不同,字段少
|
||||||
"""
|
"""
|
||||||
actions = ActionField(read_only=True)
|
actions = ActionsField(read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = SystemUser
|
model = SystemUser
|
||||||
@ -115,4 +115,4 @@ class GrantedNodeSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
|
|
||||||
class ActionsSerializer(serializers.Serializer):
|
class ActionsSerializer(serializers.Serializer):
|
||||||
actions = ActionField(read_only=True)
|
actions = ActionsField(read_only=True)
|
||||||
|
@ -6,7 +6,7 @@ from django.db import transaction
|
|||||||
|
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
from .utils import AssetPermissionUtil
|
from .utils import AssetPermissionUtil
|
||||||
from .models import AssetPermission, Action
|
from .models import AssetPermission
|
||||||
|
|
||||||
|
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
|
@ -17,7 +17,7 @@ from orgs.utils import set_to_root_org
|
|||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
from common.tree import TreeNode
|
from common.tree import TreeNode
|
||||||
from .. import const
|
from .. import const
|
||||||
from ..models import AssetPermission, Action, ActionFlag
|
from ..models import AssetPermission, Action
|
||||||
from ..hands import Node, Asset
|
from ..hands import Node, Asset
|
||||||
from assets.utils import NodeUtil
|
from assets.utils import NodeUtil
|
||||||
|
|
||||||
@ -569,7 +569,7 @@ def parse_asset_to_tree_node(node, asset, system_users):
|
|||||||
'protocol': system_user.protocol,
|
'protocol': system_user.protocol,
|
||||||
'priority': system_user.priority,
|
'priority': system_user.priority,
|
||||||
'login_mode': system_user.login_mode,
|
'login_mode': system_user.login_mode,
|
||||||
'actions': [ActionFlag.value_to_choices(action)],
|
'actions': [Action.value_to_choices(action)],
|
||||||
})
|
})
|
||||||
data = {
|
data = {
|
||||||
'id': str(asset.id),
|
'id': str(asset.id),
|
||||||
|
@ -10,10 +10,9 @@ from django.conf import settings
|
|||||||
|
|
||||||
from common.permissions import PermissionsMixin, IsOrgAdmin
|
from common.permissions import PermissionsMixin, IsOrgAdmin
|
||||||
from orgs.utils import current_org
|
from orgs.utils import current_org
|
||||||
from perms.hands import Node, Asset, SystemUser, User, UserGroup
|
from perms.hands import Node, Asset, SystemUser, UserGroup
|
||||||
from perms.models import AssetPermission, Action
|
from perms.models import AssetPermission
|
||||||
from perms.forms import AssetPermissionForm
|
from perms.forms import AssetPermissionForm
|
||||||
from perms.const import PERMS_ACTION_NAME_ALL
|
|
||||||
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
|
@ -77,6 +77,7 @@ def monkey_patch_settings(sender, **kwargs):
|
|||||||
@receiver(django_ready)
|
@receiver(django_ready)
|
||||||
def auto_generate_terminal_host_key(sender, **kwargs):
|
def auto_generate_terminal_host_key(sender, **kwargs):
|
||||||
try:
|
try:
|
||||||
|
print("Auto gen host key")
|
||||||
if Setting.objects.filter(name='TERMINAL_HOST_KEY').exists():
|
if Setting.objects.filter(name='TERMINAL_HOST_KEY').exists():
|
||||||
return
|
return
|
||||||
private_key, public_key = ssh_key_gen()
|
private_key, public_key = ssh_key_gen()
|
||||||
|
Loading…
Reference in New Issue
Block a user