# Generated by Django 4.2.14 on 2024-07-15 14:46

from django.conf import settings
import django.contrib.postgres.fields
from django.db import migrations, models
import django.db.models.deletion
import markupfield.fields
import projectroles.models
import random
import string
import uuid


def populate_roles(apps, schema_editor):
    """Populate Role objects"""
    Role = apps.get_model('projectroles', 'Role')

    def save_role(name, description):
        role = Role(name=name, description=description)
        role.save()

    # Owner
    save_role(
        'project owner',
        'The project owner has full access to project data; rights to add, '
        'modify and remove project members; right to assign a project '
        'delegate. Each project must have exactly one owner.',
    )
    # Delegate
    save_role(
        'project delegate',
        'The project delegate has all the rights of a project owner with the '
        'exception of assigning a delegate. A maximum of one delegate can be '
        'set per project. A delegate role can be set by project owner.',
    )
    # Contributor
    save_role(
        'project contributor',
        'A project member with ability to view and add project data. Can edit '
        'their own data.',
    )
    # Guest
    save_role(
        'project guest',
        'Read-only access to a project. Can view data in project, can not add '
        'or edit.',
    )


def fix_remote_project_keys(apps, schema_editor):
    """Fix missing RemoteProject.project foreign keys (issue #197)"""
    RemoteProject = apps.get_model('projectroles', 'RemoteProject')
    Project = apps.get_model('projectroles', 'Project')
    for rp in RemoteProject.objects.all():
        if not rp.project:
            rp.project = Project.objects.filter(
                sodar_uuid=rp.project_uuid
            ).first()
            rp.save()


def populate_project_full_title(apps, schema_editor):
    """Populate the new full_title field in the Project model"""

    def get_project_parents(obj):
        if not obj.parent:
            return None
        ret = []
        parent = obj.parent
        while parent:
            ret.append(parent)
            parent = parent.parent
        return reversed(ret)

    def get_project_full_title(obj):
        parents = get_project_parents(obj)
        ret = ' / '.join([p.title for p in parents]) + ' / ' if parents else ''
        ret += obj.title
        return ret

    Project = apps.get_model('projectroles', 'Project')
    for project in Project.objects.all():
        project.full_title = get_project_full_title(project)
        project.save()


def populate_public_children(apps, schema_editor):
    """Populate the new has_public_children field in the Project model"""

    def get_public_children(obj):
        for child in obj.children.all():
            if child.public_guest_access:
                return True
            ret = get_public_children(child)
            if ret:
                return True
        return False

    Project = apps.get_model('projectroles', 'Project')
    for project in Project.objects.all():
        project.has_public_children = get_public_children(project)
        project.save()


def set_role_ranks(apps, schema_editor):
    """Set rank values for existing roles"""
    role_ranking = {
        'project owner': 10,
        'project delegate': 20,
        'project contributor': 30,
        'project guest': 40,
    }
    Role = apps.get_model('projectroles', 'Role')
    for role in Role.objects.all():
        if role.name in role_ranking:
            role.rank = role_ranking[role.name]
            role.save()


def migrate_project_stars(apps, schema_editor):
    """Create project_star AppSettings from ProjectUserTag objects"""
    ProjectUserTag = apps.get_model('projectroles', 'ProjectUserTag')
    AppSetting = apps.get_model('projectroles', 'AppSetting')
    for tag in ProjectUserTag.objects.filter(name='STARRED'):
        AppSetting.objects.get_or_create(
            project=tag.project,
            user=tag.user,
            value=True,
            name='project_star',
        )


def delete_category_app_settings(apps, schema_editor):
    """Delete app settings assigned to categories"""
    from projectroles.app_settings import AppSettingAPI

    app_settings = AppSettingAPI()
    AppSetting = apps.get_model('projectroles', 'AppSetting')
    # Find all app settings whith a project
    pr_settings = AppSetting.objects.exclude(project=None)
    for app_setting in pr_settings:
        try:
            plugin_name = (
                app_setting.app_plugin.name
                if app_setting.app_plugin
                else 'projectroles'
            )
            setting_def = app_settings.get_definition(
                plugin_name=plugin_name, name=app_setting.name
            )
        except ValueError:
            app_setting.delete()
            continue
        if app_setting.project.type not in setting_def.project_types:
            # Delete app setting if it is not restricted to any project types
            app_setting.delete()


def populate_finder_role(apps, schema_editor):
    """Populate project finder role"""
    Role = apps.get_model('projectroles', 'Role')
    role = Role(
        name='project finder',
        rank=50,
        project_types=['CATEGORY'],
        description='The project finder is able to see certain details of all '
        'categories and projects under a category for this role is given. '
        'They will not have access to the apps or data of those subprojects or '
        'categories until assigned a higher role. This role can only be '
        'assigned for categories.',
    )
    role.save()


def reverse_finder_role(apps, schema_editor):
    """Reverse code for project finder role populating"""
    Role = apps.get_model('projectroles', 'Role')
    role = Role.objects.filter(name='project finder').first()
    if role:
        role.delete()


def populate_additional_email_model(apps, schema_editor):
    """
    Move existing additional email app settings into the
    SODARUserAdditionalEmail model as verified emais. Delete the settings
    objects.
    """
    AppSetting = apps.get_model('projectroles', 'AppSetting')
    SODARUserAdditionalEmail = apps.get_model(
        'projectroles', 'SODARUserAdditionalEmail'
    )
    for a in AppSetting.objects.filter(
        app_plugin=None, name='user_email_additional'
    ):
        for v in a.value.split(';'):
            secret = ''.join(
                random.SystemRandom().choice(
                    string.ascii_lowercase + string.digits
                )
                for _ in range(32)
            )
            try:
                SODARUserAdditionalEmail.objects.create(
                    user=a.user, email=v, verified=True, secret=secret
                )
            except Exception:
                pass
        a.delete()


class Migration(migrations.Migration):

    replaces = [
        ('projectroles', '0001_initial'),
        ('projectroles', '0002_auto_20180411_1758'),
        ('projectroles', '0003_populate_roles'),
        ('projectroles', '0004_rename_uuid'),
        ('projectroles', '0005_update_uuid'),
        ('projectroles', '0006_add_remote_projects'),
        ('projectroles', '0007_fix_remoteproject_foreign_key'),
        ('projectroles', '0008_auto_20190426_0606'),
        ('projectroles', '0009_rename_projectsetting'),
        ('projectroles', '0010_update_appsetting'),
        ('projectroles', '0011_remove_indexes'),
        ('projectroles', '0012_update_remotesite'),
        ('projectroles', '0013_update_appsetting_type'),
        ('projectroles', '0014_update_appsetting_value_json'),
        ('projectroles', '0015_fix_appsetting_constraint'),
        ('projectroles', '0016_app_plugin_field_none'),
        ('projectroles', '0017_project_full_title'),
        ('projectroles', '0018_update_jsonfield'),
        ('projectroles', '0019_project_public_guest_access'),
        ('projectroles', '0020_project_has_public_children'),
        ('projectroles', '0021_remove_project_submit_status'),
        ('projectroles', '0022_role_rank'),
        ('projectroles', '0023_project_archive'),
        ('projectroles', '0024_project_star_app_setting'),
        ('projectroles', '0025_delete_projectusertag'),
        ('projectroles', '0026_delete_category_settings'),
        ('projectroles', '0027_role_project_type'),
        ('projectroles', '0028_populate_finder_role'),
        ('projectroles', '0029_sodaruseradditionalemail'),
        ('projectroles', '0030_populate_sodaruseradditionalemail'),
        ('projectroles', '0031_remotesite_owner_modifiable'),
        ('projectroles', '0032_alter_appsetting_value'),
    ]

    initial = True

    dependencies = [
        ('djangoplugins', '0001_initial'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='Project',
            fields=[
                (
                    'id',
                    models.AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name='ID',
                    ),
                ),
                (
                    'title',
                    models.CharField(help_text='Project title', max_length=255),
                ),
                (
                    'type',
                    models.CharField(
                        choices=[
                            ('CATEGORY', 'Category'),
                            ('PROJECT', 'Project'),
                        ],
                        default='PROJECT',
                        help_text='Type of project ("CATEGORY", "PROJECT")',
                        max_length=64,
                    ),
                ),
                (
                    'description',
                    models.CharField(
                        help_text='Short project description', max_length=512
                    ),
                ),
                (
                    'readme',
                    markupfield.fields.MarkupField(
                        blank=True,
                        help_text='Project README (optional, supports markdown)',
                        null=True,
                        rendered_field=True,
                    ),
                ),
                (
                    'readme_markup_type',
                    models.CharField(
                        choices=[
                            ('', '--'),
                            ('html', 'HTML'),
                            ('plain', 'Plain'),
                            ('markdown', 'Markdown'),
                            ('restructuredtext', 'Restructured Text'),
                        ],
                        default='markdown',
                        editable=False,
                        max_length=30,
                    ),
                ),
                (
                    'submit_status',
                    models.CharField(
                        default='OK',
                        help_text='Status of project creation',
                        max_length=64,
                    ),
                ),
                (
                    '_readme_rendered',
                    models.TextField(editable=False, null=True),
                ),
                (
                    'omics_uuid',
                    models.UUIDField(
                        default=uuid.uuid4,
                        help_text='Project Omics UUID',
                        unique=True,
                    ),
                ),
                (
                    'parent',
                    models.ForeignKey(
                        blank=True,
                        help_text='Parent category if nested',
                        null=True,
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='children',
                        to='projectroles.project',
                    ),
                ),
            ],
            options={
                'ordering': ['parent__title', 'title'],
                'unique_together': {('title', 'parent')},
            },
        ),
        migrations.CreateModel(
            name='Role',
            fields=[
                (
                    'id',
                    models.AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name='ID',
                    ),
                ),
                (
                    'name',
                    models.CharField(
                        help_text='Name of role', max_length=64, unique=True
                    ),
                ),
                ('description', models.TextField(help_text='Role description')),
            ],
        ),
        migrations.CreateModel(
            name='ProjectUserTag',
            fields=[
                (
                    'id',
                    models.AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name='ID',
                    ),
                ),
                (
                    'name',
                    models.CharField(
                        default='STARRED',
                        help_text='Name of tag to be assigned',
                        max_length=64,
                    ),
                ),
                (
                    'omics_uuid',
                    models.UUIDField(
                        default=uuid.uuid4,
                        help_text='ProjectUserTag Omics UUID',
                        unique=True,
                    ),
                ),
                (
                    'project',
                    models.ForeignKey(
                        help_text='Project in which the tag is assigned',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='tags',
                        to='projectroles.project',
                    ),
                ),
                (
                    'user',
                    models.ForeignKey(
                        help_text='User for whom the tag is assigned',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='project_tags',
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                'ordering': ['project__title', 'user__username', 'name'],
            },
        ),
        migrations.CreateModel(
            name='ProjectInvite',
            fields=[
                (
                    'id',
                    models.AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name='ID',
                    ),
                ),
                (
                    'email',
                    models.EmailField(
                        help_text='Email address of the person to be invited',
                        max_length=254,
                    ),
                ),
                (
                    'date_created',
                    models.DateTimeField(
                        auto_now_add=True,
                        help_text='DateTime of invite creation',
                    ),
                ),
                (
                    'date_expire',
                    models.DateTimeField(
                        help_text='Expiration of invite as DateTime'
                    ),
                ),
                (
                    'message',
                    models.TextField(
                        blank=True,
                        help_text='Message to be included in the invite email (optional)',
                    ),
                ),
                (
                    'secret',
                    models.CharField(
                        help_text='Secret token provided to user with the invite',
                        max_length=255,
                        unique=True,
                    ),
                ),
                (
                    'active',
                    models.BooleanField(
                        default=True,
                        help_text='Status of the invite (False if claimed or revoked)',
                    ),
                ),
                (
                    'omics_uuid',
                    models.UUIDField(
                        default=uuid.uuid4,
                        help_text='ProjectInvite Omics UUID',
                        unique=True,
                    ),
                ),
                (
                    'issuer',
                    models.ForeignKey(
                        help_text='User who issued the invite',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='issued_invites',
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    'project',
                    models.ForeignKey(
                        help_text='Project to which the person is invited',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='invites',
                        to='projectroles.project',
                    ),
                ),
                (
                    'role',
                    models.ForeignKey(
                        help_text='Role assigned to the person',
                        on_delete=django.db.models.deletion.CASCADE,
                        to='projectroles.role',
                    ),
                ),
            ],
            options={
                'ordering': ['project__title', 'email', 'role__name'],
            },
        ),
        migrations.CreateModel(
            name='RoleAssignment',
            fields=[
                (
                    'id',
                    models.AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name='ID',
                    ),
                ),
                (
                    'omics_uuid',
                    models.UUIDField(
                        default=uuid.uuid4,
                        help_text='RoleAssignment Omics UUID',
                        unique=True,
                    ),
                ),
                (
                    'project',
                    models.ForeignKey(
                        help_text='Project in which role is assigned',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='roles',
                        to='projectroles.project',
                    ),
                ),
                (
                    'role',
                    models.ForeignKey(
                        help_text='Role to be assigned',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='assignments',
                        to='projectroles.role',
                    ),
                ),
                (
                    'user',
                    models.ForeignKey(
                        help_text='User for whom role is assigned',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='roles',
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                'ordering': [
                    'project__parent__title',
                    'project__title',
                    'role__name',
                    'user__username',
                ],
                'indexes': [
                    models.Index(
                        fields=['project'],
                        name='projectrole_project_b13795_idx',
                    ),
                    models.Index(
                        fields=['user'], name='projectrole_user_id_0e46f7_idx'
                    ),
                ],
            },
        ),
        migrations.CreateModel(
            name='ProjectSetting',
            fields=[
                (
                    'id',
                    models.AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name='ID',
                    ),
                ),
                (
                    'name',
                    models.CharField(
                        help_text='Name of the setting', max_length=255
                    ),
                ),
                (
                    'type',
                    models.CharField(
                        choices=[
                            ('BOOLEAN', 'Boolean'),
                            ('INTEGER', 'Integer'),
                            ('STRING', 'String'),
                        ],
                        help_text='Type of the setting',
                        max_length=64,
                    ),
                ),
                (
                    'value',
                    models.CharField(
                        blank=True,
                        help_text='Value of the setting',
                        max_length=255,
                        null=True,
                    ),
                ),
                (
                    'omics_uuid',
                    models.UUIDField(
                        default=uuid.uuid4,
                        help_text='ProjectSetting Omics UUID',
                        unique=True,
                    ),
                ),
                (
                    'app_plugin',
                    models.ForeignKey(
                        help_text='App to which the setting belongs',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='settings',
                        to='djangoplugins.plugin',
                    ),
                ),
                (
                    'project',
                    models.ForeignKey(
                        help_text='Project to which the setting belongs',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='settings',
                        to='projectroles.project',
                    ),
                ),
            ],
            options={
                'ordering': ['project__title', 'app_plugin__name', 'name'],
                'unique_together': {('project', 'app_plugin', 'name')},
            },
        ),
        migrations.RunPython(
            code=populate_roles,
            reverse_code=migrations.RunPython.noop,
        ),
        migrations.RenameField(
            model_name='project',
            old_name='omics_uuid',
            new_name='sodar_uuid',
        ),
        migrations.RenameField(
            model_name='projectinvite',
            old_name='omics_uuid',
            new_name='sodar_uuid',
        ),
        migrations.RenameField(
            model_name='projectsetting',
            old_name='omics_uuid',
            new_name='sodar_uuid',
        ),
        migrations.RenameField(
            model_name='projectusertag',
            old_name='omics_uuid',
            new_name='sodar_uuid',
        ),
        migrations.RenameField(
            model_name='roleassignment',
            old_name='omics_uuid',
            new_name='sodar_uuid',
        ),
        migrations.AlterField(
            model_name='project',
            name='sodar_uuid',
            field=models.UUIDField(
                default=uuid.uuid4, help_text='Project SODAR UUID', unique=True
            ),
        ),
        migrations.AlterField(
            model_name='projectinvite',
            name='sodar_uuid',
            field=models.UUIDField(
                default=uuid.uuid4,
                help_text='ProjectInvite SODAR UUID',
                unique=True,
            ),
        ),
        migrations.AlterField(
            model_name='projectsetting',
            name='sodar_uuid',
            field=models.UUIDField(
                default=uuid.uuid4,
                help_text='ProjectSetting SODAR UUID',
                unique=True,
            ),
        ),
        migrations.AlterField(
            model_name='projectusertag',
            name='sodar_uuid',
            field=models.UUIDField(
                default=uuid.uuid4,
                help_text='ProjectUserTag SODAR UUID',
                unique=True,
            ),
        ),
        migrations.AlterField(
            model_name='roleassignment',
            name='sodar_uuid',
            field=models.UUIDField(
                default=uuid.uuid4,
                help_text='RoleAssignment SODAR UUID',
                unique=True,
            ),
        ),
        migrations.AlterField(
            model_name='project',
            name='description',
            field=models.CharField(
                blank=True,
                help_text='Short project description',
                max_length=512,
                null=True,
            ),
        ),
        migrations.CreateModel(
            name='RemoteSite',
            fields=[
                (
                    'id',
                    models.AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name='ID',
                    ),
                ),
                (
                    'name',
                    models.CharField(
                        help_text='Site name', max_length=255, unique=True
                    ),
                ),
                ('url', models.URLField(help_text='Site URL', max_length=2000)),
                (
                    'mode',
                    models.CharField(
                        default='TARGET', help_text='Site mode', max_length=64
                    ),
                ),
                ('description', models.TextField(help_text='Site description')),
                (
                    'secret',
                    models.CharField(
                        help_text='Secret token for connecting to the source site',
                        max_length=255,
                    ),
                ),
                (
                    'sodar_uuid',
                    models.UUIDField(
                        default=uuid.uuid4,
                        help_text='RemoteSite relation UUID (local)',
                        unique=True,
                    ),
                ),
            ],
            options={
                'ordering': ['name'],
                'unique_together': {('url', 'mode', 'secret')},
            },
        ),
        migrations.CreateModel(
            name='RemoteProject',
            fields=[
                (
                    'id',
                    models.AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name='ID',
                    ),
                ),
                (
                    'project_uuid',
                    models.UUIDField(default=None, help_text='Project UUID'),
                ),
                (
                    'level',
                    models.CharField(
                        default='NONE',
                        help_text='Project access level',
                        max_length=255,
                    ),
                ),
                (
                    'date_access',
                    models.DateTimeField(
                        help_text='DateTime of last access from/to remote site',
                        null=True,
                    ),
                ),
                (
                    'sodar_uuid',
                    models.UUIDField(
                        default=uuid.uuid4,
                        help_text='RemoteProject relation UUID (local)',
                        unique=True,
                    ),
                ),
                (
                    'project',
                    models.ForeignKey(
                        blank=True,
                        help_text='Related project object (if created locally)',
                        null=True,
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='remotes',
                        to='projectroles.project',
                    ),
                ),
                (
                    'site',
                    models.ForeignKey(
                        help_text='Remote SODAR site',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='projects',
                        to='projectroles.remotesite',
                    ),
                ),
            ],
            options={
                'ordering': ['site__name', 'project_uuid'],
            },
        ),
        migrations.RunPython(
            code=fix_remote_project_keys,
            reverse_code=migrations.RunPython.noop,
        ),
        migrations.AddField(
            model_name='projectsetting',
            name='user',
            field=models.ForeignKey(
                blank=True,
                help_text='User to which the setting belongs',
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name='user_settings',
                to=settings.AUTH_USER_MODEL,
            ),
        ),
        migrations.AlterField(
            model_name='projectsetting',
            name='project',
            field=models.ForeignKey(
                blank=True,
                help_text='Project to which the setting belongs',
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name='settings',
                to='projectroles.project',
            ),
        ),
        migrations.CreateModel(
            name='AppSetting',
            fields=[
                (
                    'id',
                    models.AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name='ID',
                    ),
                ),
                (
                    'name',
                    models.CharField(
                        help_text='Name of the setting', max_length=255
                    ),
                ),
                (
                    'type',
                    models.CharField(
                        choices=[
                            ('BOOLEAN', 'Boolean'),
                            ('INTEGER', 'Integer'),
                            ('STRING', 'String'),
                        ],
                        help_text='Type of the setting',
                        max_length=64,
                    ),
                ),
                (
                    'value',
                    models.CharField(
                        blank=True,
                        help_text='Value of the setting',
                        max_length=255,
                        null=True,
                    ),
                ),
                (
                    'sodar_uuid',
                    models.UUIDField(
                        default=uuid.uuid4,
                        help_text='AppSetting SODAR UUID',
                        unique=True,
                    ),
                ),
                (
                    'app_plugin',
                    models.ForeignKey(
                        help_text='App to which the setting belongs',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='settings',
                        to='djangoplugins.plugin',
                    ),
                ),
                (
                    'project',
                    models.ForeignKey(
                        blank=True,
                        help_text='Project to which the setting belongs',
                        null=True,
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='settings',
                        to='projectroles.project',
                    ),
                ),
                (
                    'user',
                    models.ForeignKey(
                        blank=True,
                        help_text='User to which the setting belongs',
                        null=True,
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='user_settings',
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    'user_modifiable',
                    models.BooleanField(
                        default=True, help_text='Setting visibility in forms'
                    ),
                ),
                (
                    'value_json',
                    django.contrib.postgres.fields.jsonb.JSONField(
                        default=dict,
                        help_text='Optional JSON value for the setting',
                    ),
                ),
            ],
            options={
                'ordering': ['project__title', 'app_plugin__name', 'name'],
                # 'unique_together': {('project', 'app_plugin', 'name')},
            },
        ),
        migrations.DeleteModel(
            name='ProjectSetting',
        ),
        migrations.RemoveIndex(
            model_name='roleassignment',
            name='projectrole_project_b13795_idx',
        ),
        migrations.RemoveIndex(
            model_name='roleassignment',
            name='projectrole_user_id_0e46f7_idx',
        ),
        migrations.AddField(
            model_name='remotesite',
            name='user_display',
            field=models.BooleanField(
                default=True, help_text='RemoteSite visibility to users'
            ),
        ),
        migrations.AlterField(
            model_name='remotesite',
            name='secret',
            field=models.CharField(
                help_text='Secret token for connecting to the source site',
                max_length=255,
                null=True,
            ),
        ),
        migrations.AlterField(
            model_name='appsetting',
            name='type',
            field=models.CharField(
                help_text='Type of the setting', max_length=64
            ),
        ),
        migrations.AlterField(
            model_name='appsetting',
            name='value_json',
            field=django.contrib.postgres.fields.jsonb.JSONField(
                default=dict,
                help_text='Optional JSON value for the setting',
                null=True,
            ),
        ),
        migrations.AlterUniqueTogether(
            name='appsetting',
            unique_together={('project', 'user', 'app_plugin', 'name')},
        ),
        migrations.AlterField(
            model_name='appsetting',
            name='app_plugin',
            field=models.ForeignKey(
                help_text='App to which the setting belongs',
                null=True,
                on_delete=django.db.models.deletion.CASCADE,
                related_name='settings',
                to='djangoplugins.plugin',
            ),
        ),
        migrations.AddField(
            model_name='project',
            name='full_title',
            field=models.CharField(
                help_text='Full project title with parent path (auto-generated)',
                max_length=4096,
                null=True,
            ),
        ),
        migrations.RunPython(
            code=populate_project_full_title,
            reverse_code=migrations.RunPython.noop,
        ),
        migrations.AlterField(
            model_name='appsetting',
            name='value_json',
            field=models.JSONField(
                default=dict,
                help_text='Optional JSON value for the setting',
                null=True,
            ),
        ),
        migrations.AddField(
            model_name='project',
            name='public_guest_access',
            field=models.BooleanField(
                default=False,
                help_text='Allow public guest access for the project, also including unauthenticated users if allowed on the site',
            ),
        ),
        migrations.AddField(
            model_name='project',
            name='has_public_children',
            field=models.BooleanField(
                default=False,
                help_text='Whether project has children with public access (auto-generated)',
            ),
        ),
        migrations.RunPython(
            code=populate_public_children,
            reverse_code=migrations.RunPython.noop,
        ),
        migrations.RemoveField(
            model_name='project',
            name='submit_status',
        ),
        migrations.AddField(
            model_name='role',
            name='rank',
            field=models.IntegerField(
                default=0, help_text='Role rank for determining role hierarchy'
            ),
        ),
        migrations.RunPython(
            code=set_role_ranks,
            reverse_code=migrations.RunPython.noop,
        ),
        migrations.AddField(
            model_name='project',
            name='archive',
            field=models.BooleanField(
                default=False, help_text='Project is archived (read-only)'
            ),
        ),
        migrations.RunPython(
            code=migrate_project_stars,
            reverse_code=migrations.RunPython.noop,
        ),
        migrations.DeleteModel(
            name='ProjectUserTag',
        ),
        migrations.RunPython(
            code=delete_category_app_settings,
            reverse_code=migrations.RunPython.noop,
        ),
        migrations.AddField(
            model_name='role',
            name='project_types',
            field=django.contrib.postgres.fields.ArrayField(
                base_field=models.CharField(max_length=64),
                default=projectroles.models.get_role_project_type_default,
                help_text='Allowed project types for the role',
                size=None,
            ),
        ),
        migrations.AlterField(
            model_name='roleassignment',
            name='project',
            field=models.ForeignKey(
                help_text='Project in which role is assigned',
                on_delete=django.db.models.deletion.CASCADE,
                related_name='local_roles',
                to='projectroles.project',
            ),
        ),
        migrations.RunPython(
            code=populate_finder_role,
            reverse_code=reverse_finder_role,
        ),
        migrations.CreateModel(
            name='SODARUserAdditionalEmail',
            fields=[
                (
                    'id',
                    models.AutoField(
                        auto_created=True,
                        primary_key=True,
                        serialize=False,
                        verbose_name='ID',
                    ),
                ),
                (
                    'email',
                    models.EmailField(
                        help_text='Email address', max_length=254
                    ),
                ),
                (
                    'verified',
                    models.BooleanField(
                        default=False, help_text='Email verification status'
                    ),
                ),
                (
                    'secret',
                    models.CharField(
                        help_text='Secret token for email verification',
                        max_length=255,
                        unique=True,
                    ),
                ),
                (
                    'date_created',
                    models.DateTimeField(
                        auto_now_add=True, help_text='DateTime of creation'
                    ),
                ),
                (
                    'date_modified',
                    models.DateTimeField(
                        auto_now=True, help_text='DateTime of last modification'
                    ),
                ),
                (
                    'sodar_uuid',
                    models.UUIDField(
                        default=uuid.uuid4,
                        help_text='SODARUserAdditionalEmail SODAR UUID',
                        unique=True,
                    ),
                ),
                (
                    'user',
                    models.ForeignKey(
                        help_text='User for whom the email is assigned',
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name='additional_emails',
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                'ordering': ['user__username', 'email'],
                'unique_together': {('user', 'email')},
            },
        ),
        migrations.RunPython(
            code=populate_additional_email_model,
            reverse_code=migrations.RunPython.noop,
        ),
        migrations.AddField(
            model_name='remotesite',
            name='owner_modifiable',
            field=models.BooleanField(
                default=True,
                help_text='Allow owners and delegates to modify project access for this site',
            ),
        ),
        migrations.AlterField(
            model_name='remotesite',
            name='user_display',
            field=models.BooleanField(
                default=True, help_text='Display site to users'
            ),
        ),
        migrations.AlterField(
            model_name='appsetting',
            name='value',
            field=models.CharField(
                blank=True, help_text='Value of the setting', null=True
            ),
        ),
    ]
