# Generated by Django 3.0.7 on 2020-08-04 22:04

from random import choices, randint
from string import ascii_letters, digits, punctuation

from django.contrib.auth.hashers import UNUSABLE_PASSWORD_PREFIX, make_password
from django.db import migrations

# Just want to highlight that we are distinguishing between these two.
ALLAUTH_ACCOUNT_APP = "account"
LOOKIT_ACCOUNTS_APP = "accounts"


def at_least_six(chars):
    return choices(chars, k=randint(6, 12))


def generate_valid_password():
    """Generate a random password of at least 18 characters.

    Ensures that we're alphanumeric + punctuated.
    """
    return "".join(
        at_least_six(ascii_letters) + at_least_six(digits) + at_least_six(punctuation)
    )


def shim_usable_passwords(apps, schema_editor):
    """Create usable passwords for OSF-based users.

    This will force them to do a password reset.
    """
    UserModel = apps.get_model(LOOKIT_ACCOUNTS_APP, "User")  # noqa
    for user in UserModel.objects.filter(
        password__startswith=UNUSABLE_PASSWORD_PREFIX, is_researcher=True
    ):
        user.password = make_password(generate_valid_password())
        user.save()


DELETE_ALLAUTH_SQL = """
-- Remove Django migrations
DELETE FROM django_migrations 
    WHERE app IN ('{allauth_account_app_name}', 'socialaccount');

-- Get rid of permissions.
DELETE FROM auth_permission
    WHERE content_type_id in (
        SELECT id FROM django_content_type 
            WHERE app_label IN ('{allauth_account_app_name}', 'socialaccount')
    );

-- Get rid of admin changes.
DELETE FROM django_admin_log
    WHERE content_type_id in (
        SELECT id FROM django_content_type
            WHERE app_label IN ('{allauth_account_app_name}', 'socialaccount')
    );

-- Delete the content types.
DELETE FROM django_content_type 
    WHERE app_label IN ('{allauth_account_app_name}', 'socialaccount');
    
-- Drop tables

DROP TABLE IF EXISTS account_emailconfirmation CASCADE;
DROP TABLE IF EXISTS account_emailaddress;

DROP TABLE IF EXISTS socialaccount_socialtoken CASCADE;
DROP TABLE IF EXISTS socialaccount_socialapp_sites CASCADE;
DROP TABLE IF EXISTS socialaccount_socialapp CASCADE;
DROP TABLE IF EXISTS socialaccount_socialaccount;
""".format(
    allauth_account_app_name=ALLAUTH_ACCOUNT_APP
)


class Migration(migrations.Migration):

    dependencies = [
        ("admin", "0003_logentry_add_action_flag_choices"),
        # If we don't add the above, tests will fail due to the fact that
        # we use a custom default admin site.
        # TODO: Investigate why and where Django's test harness fails to create
        #   these models, and then either file a bug or use a better fix.
        ("accounts", "0048_add_otp_model"),
    ]

    operations = [
        migrations.RunSQL(DELETE_ALLAUTH_SQL),
        migrations.RunPython(shim_usable_passwords),
    ]
