diff --git a/apps/assets/migrations/0001_initial.py b/apps/assets/migrations/0001_initial.py new file mode 100644 index 000000000..7c0a9e95a --- /dev/null +++ b/apps/assets/migrations/0001_initial.py @@ -0,0 +1,168 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2017-12-21 16:06 +from __future__ import unicode_literals + +import assets.models.utils +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +def add_default_group(apps, schema_editor): + group_model = apps.get_model("assets", "AssetGroup") + db_alias = schema_editor.connection.alias + group_model.objects.using(db_alias).create( + name="Default" + ) + + +def add_default_cluster(apps, schema_editor): + cluster_model = apps.get_model("assets", "Cluster") + db_alias = schema_editor.connection.alias + cluster_model.objects.using(db_alias).create( + name="Default" + ) + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='AdminUser', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('username', models.CharField(max_length=16, verbose_name='Username')), + ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), + ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), + ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('date_updated', models.DateTimeField(auto_now=True)), + ('created_by', models.CharField(max_length=32, null=True, verbose_name='Created by')), + ('become', models.BooleanField(default=True)), + ('become_method', models.CharField(choices=[('sudo', 'sudo'), ('su', 'su')], default='sudo', max_length=4)), + ('become_user', models.CharField(default='root', max_length=64)), + ('_become_pass', models.CharField(default='', max_length=128)), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='Asset', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('ip', models.GenericIPAddressField(db_index=True, verbose_name='IP')), + ('hostname', models.CharField(max_length=128, unique=True, verbose_name='Hostname')), + ('port', models.IntegerField(default=22, verbose_name='Port')), + ('is_active', models.BooleanField(default=True, verbose_name='Is active')), + ('type', models.CharField(blank=True, choices=[('Server', 'Server'), ('VM', 'VM'), ('Switch', 'Switch'), ('Router', 'Router'), ('Firewall', 'Firewall'), ('Storage', 'Storage')], default='Server', max_length=16, null=True, verbose_name='Asset type')), + ('env', models.CharField(blank=True, choices=[('Prod', 'Production'), ('Dev', 'Development'), ('Test', 'Testing')], default='Prod', max_length=8, null=True, verbose_name='Asset environment')), + ('status', models.CharField(blank=True, choices=[('In use', 'In use'), ('Out of use', 'Out of use')], default='In use', max_length=12, null=True, verbose_name='Asset status')), + ('public_ip', models.GenericIPAddressField(blank=True, null=True, verbose_name='Public IP')), + ('remote_card_ip', models.CharField(blank=True, max_length=16, null=True, verbose_name='Remote control card IP')), + ('cabinet_no', models.CharField(blank=True, max_length=32, null=True, verbose_name='Cabinet number')), + ('cabinet_pos', models.IntegerField(blank=True, null=True, verbose_name='Cabinet position')), + ('number', models.CharField(blank=True, max_length=32, null=True, verbose_name='Asset number')), + ('vendor', models.CharField(blank=True, max_length=64, null=True, verbose_name='Vendor')), + ('model', models.CharField(blank=True, max_length=54, null=True, verbose_name='Model')), + ('sn', models.CharField(blank=True, max_length=128, null=True, verbose_name='Serial number')), + ('cpu_model', models.CharField(blank=True, max_length=64, null=True, verbose_name='CPU model')), + ('cpu_count', models.IntegerField(null=True, verbose_name='CPU count')), + ('cpu_cores', models.IntegerField(null=True, verbose_name='CPU cores')), + ('memory', models.CharField(blank=True, max_length=64, null=True, verbose_name='Memory')), + ('disk_total', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Disk total')), + ('disk_info', models.CharField(blank=True, max_length=1024, null=True, verbose_name='Disk info')), + ('platform', models.CharField(blank=True, max_length=128, null=True, verbose_name='Platform')), + ('os', models.CharField(blank=True, max_length=128, null=True, verbose_name='OS')), + ('os_version', models.CharField(blank=True, max_length=16, null=True, verbose_name='OS version')), + ('os_arch', models.CharField(blank=True, max_length=16, null=True, verbose_name='OS arch')), + ('hostname_raw', models.CharField(blank=True, max_length=128, null=True, verbose_name='Hostname raw')), + ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('comment', models.TextField(blank=True, default='', max_length=128, verbose_name='Comment')), + ('admin_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.AdminUser', verbose_name='Admin user')), + ], + ), + migrations.CreateModel( + name='AssetGroup', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=64, unique=True, verbose_name='Name')), + ('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='Cluster', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=32, verbose_name='Name')), + ('bandwidth', models.CharField(blank=True, max_length=32, verbose_name='Bandwidth')), + ('contact', models.CharField(blank=True, max_length=128, verbose_name='Contact')), + ('phone', models.CharField(blank=True, max_length=32, verbose_name='Phone')), + ('address', models.CharField(blank=True, max_length=128, verbose_name='Address')), + ('intranet', models.TextField(blank=True, verbose_name='Intranet')), + ('extranet', models.TextField(blank=True, verbose_name='Extranet')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('operator', models.CharField(blank=True, max_length=32, verbose_name='Operator')), + ('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ('admin_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.AdminUser', verbose_name='Admin user')), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.CreateModel( + name='SystemUser', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('username', models.CharField(max_length=16, verbose_name='Username')), + ('_password', models.CharField(blank=True, max_length=256, null=True, verbose_name='Password')), + ('_private_key', models.TextField(blank=True, max_length=4096, null=True, validators=[assets.models.utils.private_key_validator], verbose_name='SSH private key')), + ('_public_key', models.TextField(blank=True, max_length=4096, verbose_name='SSH public key')), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('date_updated', models.DateTimeField(auto_now=True)), + ('created_by', models.CharField(max_length=32, null=True, verbose_name='Created by')), + ('priority', models.IntegerField(default=10, verbose_name='Priority')), + ('protocol', models.CharField(choices=[('ssh', 'ssh')], default='ssh', max_length=16, verbose_name='Protocol')), + ('auto_push', models.BooleanField(default=True, verbose_name='Auto push')), + ('sudo', models.TextField(default='/sbin/ifconfig', verbose_name='Sudo')), + ('shell', models.CharField(default='/bin/bash', max_length=64, verbose_name='Shell')), + ('cluster', models.ManyToManyField(blank=True, to='assets.Cluster', verbose_name='Cluster')), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.AddField( + model_name='asset', + name='cluster', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assets', to='assets.Cluster', verbose_name='Cluster'), + ), + migrations.AddField( + model_name='asset', + name='groups', + field=models.ManyToManyField(blank=True, related_name='assets', to='assets.AssetGroup', verbose_name='Asset groups'), + ), + migrations.AlterUniqueTogether( + name='asset', + unique_together=set([('ip', 'port')]), + ), + + migrations.RunPython(add_default_cluster), + migrations.RunPython(add_default_group), + ] diff --git a/apps/assets/migrations/__init__.py b/apps/assets/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/common/migrations/__init__.py b/apps/common/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/ops/migrations/0001_initial.py b/apps/ops/migrations/0001_initial.py new file mode 100644 index 000000000..13adf43a8 --- /dev/null +++ b/apps/ops/migrations/0001_initial.py @@ -0,0 +1,84 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2017-12-24 15:21 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='AdHoc', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('_tasks', models.TextField(verbose_name='Tasks')), + ('pattern', models.CharField(default='{}', max_length=64, verbose_name='Pattern')), + ('_options', models.CharField(default='', max_length=1024, verbose_name='Options')), + ('_hosts', models.TextField(blank=True, verbose_name='Hosts')), + ('run_as_admin', models.BooleanField(default=False, verbose_name='Run as admin')), + ('run_as', models.CharField(default='', max_length=128, verbose_name='Run as')), + ('_become', models.CharField(default='', max_length=1024, verbose_name='Become')), + ('created_by', models.CharField(default='', max_length=64, null=True, verbose_name='Create by')), + ('date_created', models.DateTimeField(auto_now_add=True)), + ], + options={ + 'db_table': 'ops_adhoc', + 'get_latest_by': 'date_created', + }, + ), + migrations.CreateModel( + name='AdHocRunHistory', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('date_start', models.DateTimeField(auto_now_add=True, verbose_name='Start time')), + ('date_finished', models.DateTimeField(blank=True, null=True, verbose_name='End time')), + ('timedelta', models.FloatField(default=0.0, null=True, verbose_name='Time')), + ('is_finished', models.BooleanField(default=False, verbose_name='Is finished')), + ('is_success', models.BooleanField(default=False, verbose_name='Is success')), + ('_result', models.TextField(blank=True, null=True, verbose_name='Adhoc raw result')), + ('_summary', models.TextField(blank=True, null=True, verbose_name='Adhoc result summary')), + ('adhoc', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='history', to='ops.AdHoc')), + ], + options={ + 'db_table': 'ops_adhoc_history', + 'get_latest_by': 'date_start', + }, + ), + migrations.CreateModel( + name='Task', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('interval', models.IntegerField(blank=True, help_text='Units: seconds', null=True, verbose_name='Interval')), + ('crontab', models.CharField(blank=True, help_text='5 * * * *', max_length=128, null=True, verbose_name='Crontab')), + ('is_periodic', models.BooleanField(default=False)), + ('callback', models.CharField(blank=True, max_length=128, null=True, verbose_name='Callback')), + ('is_deleted', models.BooleanField(default=False)), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ('created_by', models.CharField(blank=True, default='', max_length=128, null=True)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ], + options={ + 'db_table': 'ops_task', + 'get_latest_by': 'date_created', + }, + ), + migrations.AddField( + model_name='adhocrunhistory', + name='task', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='history', to='ops.Task'), + ), + migrations.AddField( + model_name='adhoc', + name='task', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='adhoc', to='ops.Task'), + ), + ] diff --git a/apps/ops/migrations/__init__.py b/apps/ops/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/perms/migrations/0001_initial.py b/apps/perms/migrations/0001_initial.py new file mode 100644 index 000000000..63605a247 --- /dev/null +++ b/apps/perms/migrations/0001_initial.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2017-12-24 15:21 +from __future__ import unicode_literals + +import common.utils +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('assets', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='AssetPermission', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, unique=True, verbose_name='Name')), + ('is_active', models.BooleanField(default=True, verbose_name='Active')), + ('date_expired', models.DateTimeField(default=common.utils.date_expired_default, verbose_name='Date expired')), + ('created_by', models.CharField(blank=True, max_length=128, verbose_name='Created by')), + ('date_created', models.DateTimeField(auto_now_add=True, verbose_name='Date created')), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ('asset_groups', models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.AssetGroup', verbose_name='Asset group')), + ('assets', models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.Asset', verbose_name='Asset')), + ('system_users', models.ManyToManyField(related_name='granted_by_permissions', to='assets.SystemUser', verbose_name='System user')), + ], + ), + ] diff --git a/apps/perms/migrations/__init__.py b/apps/perms/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/terminal/migrations/0001_initial.py b/apps/terminal/migrations/0001_initial.py new file mode 100644 index 000000000..fe604fc01 --- /dev/null +++ b/apps/terminal/migrations/0001_initial.py @@ -0,0 +1,102 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2017-12-24 15:21 +from __future__ import unicode_literals + +from django.db import migrations, models +import uuid + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Command', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('user', models.CharField(max_length=64, verbose_name='User')), + ('asset', models.CharField(max_length=128, verbose_name='Asset')), + ('system_user', models.CharField(max_length=64, verbose_name='System user')), + ('input', models.CharField(db_index=True, max_length=128, verbose_name='Input')), + ('output', models.CharField(blank=True, max_length=1024, verbose_name='Output')), + ('session', models.CharField(db_index=True, max_length=36, verbose_name='Session')), + ('timestamp', models.IntegerField(db_index=True)), + ], + options={ + 'db_table': 'terminal_command', + 'ordering': ('-timestamp',), + }, + ), + migrations.CreateModel( + name='Session', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('user', models.CharField(max_length=128, verbose_name='User')), + ('asset', models.CharField(max_length=1024, verbose_name='Asset')), + ('system_user', models.CharField(max_length=128, verbose_name='System user')), + ('login_from', models.CharField(choices=[('ST', 'SSH Terminal'), ('WT', 'Web Terminal')], default='ST', max_length=2)), + ('is_finished', models.BooleanField(default=False)), + ('has_replay', models.BooleanField(default=False, verbose_name='Replay')), + ('has_command', models.BooleanField(default=False, verbose_name='Command')), + ('date_start', models.DateTimeField(verbose_name='Date start')), + ('date_end', models.DateTimeField(null=True, verbose_name='Date end')), + ], + options={ + 'db_table': 'terminal_session', + 'ordering': ['-date_start'], + }, + ), + migrations.CreateModel( + name='Status', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('session_online', models.IntegerField(default=0, verbose_name='Session Online')), + ('cpu_used', models.FloatField(verbose_name='CPU Usage')), + ('memory_used', models.FloatField(verbose_name='Memory Used')), + ('connections', models.IntegerField(verbose_name='Connections')), + ('threads', models.IntegerField(verbose_name='Threads')), + ('boot_time', models.FloatField(verbose_name='Boot Time')), + ('date_created', models.DateTimeField(auto_now_add=True)), + ], + options={ + 'db_table': 'terminal_status', + 'get_latest_by': 'date_created', + }, + ), + migrations.CreateModel( + name='Task', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(choices=[('kill_session', 'Kill Session')], max_length=128, verbose_name='Name')), + ('args', models.CharField(max_length=1024, verbose_name='Args')), + ('is_finished', models.BooleanField(default=False)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('date_finished', models.DateTimeField(null=True)), + ], + options={ + 'db_table': 'terminal_task', + }, + ), + migrations.CreateModel( + name='Terminal', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=32, unique=True, verbose_name='Name')), + ('remote_addr', models.CharField(max_length=128, verbose_name='Remote Address')), + ('ssh_port', models.IntegerField(default=2222, verbose_name='SSH Port')), + ('http_port', models.IntegerField(default=5000, verbose_name='HTTP Port')), + ('is_accepted', models.BooleanField(default=False, verbose_name='Is Accepted')), + ('is_deleted', models.BooleanField(default=False)), + ('date_created', models.DateTimeField(auto_now_add=True)), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ], + options={ + 'db_table': 'terminal', + 'ordering': ('is_accepted',), + }, + ), + ] diff --git a/apps/terminal/migrations/__init__.py b/apps/terminal/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/apps/users/migrations/0001_initial.py b/apps/users/migrations/0001_initial.py new file mode 100644 index 000000000..01edf24b6 --- /dev/null +++ b/apps/users/migrations/0001_initial.py @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11 on 2017-12-21 16:06 +from __future__ import unicode_literals + +import common.utils +from django.contrib.auth.hashers import make_password +from django.conf import settings +import django.contrib.auth.models +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone +import uuid + + +def add_default_group(apps, schema_editor): + group_model = apps.get_model("users", "UserGroup") + db_alias = schema_editor.connection.alias + group_model.objects.using(db_alias).create( + name="Default" + ) + + +def add_default_admin(apps, schema_editor): + user_model = apps.get_model("users", "User") + db_alias = schema_editor.connection.alias + admin = user_model.objects.using(db_alias).create( + username="admin", name="Administrator", + email="admin@mycomany.com", role="Admin", + password=make_password("admin"), + ) + group_model = apps.get_model("users", "UserGroup") + default_group = group_model.objects.using(db_alias).get(name="Default") + admin.groups.add(default_group) + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('auth', '0008_alter_user_username_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='User', + fields=[ + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('first_name', models.CharField(blank=True, max_length=30, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=30, verbose_name='last name')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('username', models.CharField(max_length=20, unique=True, verbose_name='Username')), + ('name', models.CharField(max_length=20, verbose_name='Name')), + ('email', models.EmailField(max_length=30, unique=True, verbose_name='Email')), + ('role', models.CharField(blank=True, choices=[('Admin', 'Administrator'), ('User', 'User'), ('App', 'Application')], default='User', max_length=10, verbose_name='Role')), + ('avatar', models.ImageField(null=True, upload_to='avatar', verbose_name='Avatar')), + ('wechat', models.CharField(blank=True, max_length=30, verbose_name='Wechat')), + ('phone', models.CharField(blank=True, max_length=20, null=True, verbose_name='Phone')), + ('enable_otp', models.BooleanField(default=False, verbose_name='Enable OTP')), + ('secret_key_otp', models.CharField(blank=True, max_length=16)), + ('_private_key', models.CharField(blank=True, max_length=5000, verbose_name='Private key')), + ('_public_key', models.CharField(blank=True, max_length=5000, verbose_name='Public key')), + ('comment', models.TextField(blank=True, max_length=200, verbose_name='Comment')), + ('is_first_login', models.BooleanField(default=False)), + ('date_expired', models.DateTimeField(blank=True, default=common.utils.date_expired_default, null=True, verbose_name='Date expired')), + ('created_by', models.CharField(default='', max_length=30, verbose_name='Created by')), + ], + options={ + 'ordering': ['username'], + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.CreateModel( + name='AccessKey', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, verbose_name='AccessKeyID')), + ('secret', models.UUIDField(default=uuid.uuid4, editable=False, verbose_name='AccessKeySecret')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='access_key', to=settings.AUTH_USER_MODEL, verbose_name='User')), + ], + ), + migrations.CreateModel( + name='LoginLog', + fields=[ + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('username', models.CharField(max_length=20, verbose_name='Username')), + ('type', models.CharField(choices=[('W', 'Web'), ('T', 'Terminal')], max_length=2, verbose_name='Login type')), + ('ip', models.GenericIPAddressField(verbose_name='Login ip')), + ('city', models.CharField(blank=True, max_length=254, null=True, verbose_name='Login city')), + ('user_agent', models.CharField(blank=True, max_length=254, null=True, verbose_name='User agent')), + ('datetime', models.DateTimeField(auto_now_add=True, verbose_name='Date login')), + ], + options={ + 'ordering': ['-datetime', 'username'], + }, + ), + migrations.CreateModel( + name='PrivateToken', + fields=[ + ('key', models.CharField(max_length=40, primary_key=True, serialize=False, verbose_name='Key')), + ('created', models.DateTimeField(auto_now_add=True, verbose_name='Created')), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='auth_token', to=settings.AUTH_USER_MODEL, verbose_name='User')), + ], + options={ + 'verbose_name': 'Private Token', + }, + ), + migrations.CreateModel( + name='UserGroup', + fields=[ + ('is_discard', models.BooleanField(default=False, verbose_name='is discard')), + ('discard_time', models.DateTimeField(blank=True, null=True, verbose_name='discard time')), + ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), + ('name', models.CharField(max_length=128, verbose_name='Name')), + ('comment', models.TextField(blank=True, verbose_name='Comment')), + ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), + ('created_by', models.CharField(max_length=100)), + ], + options={ + 'ordering': ['name'], + }, + ), + migrations.AddField( + model_name='user', + name='groups', + field=models.ManyToManyField(blank=True, related_name='users', to='users.UserGroup', verbose_name='User group'), + ), + migrations.AddField( + model_name='user', + name='user_permissions', + field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'), + ), + migrations.RunPython(add_default_group), + migrations.RunPython(add_default_admin), + ] diff --git a/apps/users/migrations/__init__.py b/apps/users/migrations/__init__.py new file mode 100644 index 000000000..e69de29bb