Migrations, etc

This commit is contained in:
zandercymatics 2024-04-30 10:52:53 -06:00
parent f52a7e08fe
commit 5e2ec5d1c8
No known key found for this signature in database
GPG key ID: FF4636ABEC9682B7
8 changed files with 103 additions and 4 deletions

View file

@ -15,7 +15,9 @@ from django.contrib.contenttypes.models import ContentType
from django.urls import reverse from django.urls import reverse
from dateutil.relativedelta import relativedelta # type: ignore from dateutil.relativedelta import relativedelta # type: ignore
from epplibwrapper.errors import ErrorCode, RegistryError from epplibwrapper.errors import ErrorCode, RegistryError
from waffle.admin import FlagAdmin
from registrar.models import Contact, Domain, DomainRequest, DraftDomain, User, Website from registrar.models import Contact, Domain, DomainRequest, DraftDomain, User, Website
from waffle.models import Sample, Switch
from registrar.utility.errors import FSMDomainRequestError, FSMErrorCodes from registrar.utility.errors import FSMDomainRequestError, FSMErrorCodes
from registrar.views.utility.mixins import OrderableFieldsMixin from registrar.views.utility.mixins import OrderableFieldsMixin
from django.contrib.admin.views.main import ORDER_VAR from django.contrib.admin.views.main import ORDER_VAR
@ -2157,8 +2159,19 @@ class UserGroupAdmin(AuditedAdmin):
def user_group(self, obj): def user_group(self, obj):
return obj.name return obj.name
class WaffleFlagAdmin(FlagAdmin):
class Meta:
"""Contains meta information about this class"""
model = models.WaffleFlag
fields = "__all__"
admin.site.unregister(LogEntry) # Unregister the default registration admin.site.unregister(LogEntry) # Unregister the default registration
# Unregister samples and switches from django-waffle, as we currently don't use these.
# TODO - address this
admin.site.unregister(Sample)
admin.site.unregister(Switch)
admin.site.register(LogEntry, CustomLogEntryAdmin) admin.site.register(LogEntry, CustomLogEntryAdmin)
admin.site.register(models.User, MyUserAdmin) admin.site.register(models.User, MyUserAdmin)
# Unregister the built-in Group model # Unregister the built-in Group model
@ -2180,3 +2193,6 @@ admin.site.register(models.PublicContact, PublicContactAdmin)
admin.site.register(models.DomainRequest, DomainRequestAdmin) admin.site.register(models.DomainRequest, DomainRequestAdmin)
admin.site.register(models.TransitionDomain, TransitionDomainAdmin) admin.site.register(models.TransitionDomain, TransitionDomainAdmin)
admin.site.register(models.VerifiedByStaff, VerifiedByStaffAdmin) admin.site.register(models.VerifiedByStaff, VerifiedByStaffAdmin)
# Register our custom waffle flag implementation
admin.site.register(models.WaffleFlag, WaffleFlagAdmin)

View file

@ -22,7 +22,6 @@ from base64 import b64decode
from cfenv import AppEnv # type: ignore from cfenv import AppEnv # type: ignore
from pathlib import Path from pathlib import Path
from typing import Final from typing import Final
from botocore.config import Config from botocore.config import Config
# # # ### # # # ###
@ -326,7 +325,10 @@ SERVER_EMAIL = "root@get.gov"
# region: Waffle feature flags-----------------------------------------------------------### # region: Waffle feature flags-----------------------------------------------------------###
# If Waffle encounters a reference to a flag that is not in the database, should Waffle create the flag? # If Waffle encounters a reference to a flag that is not in the database, should Waffle create the flag?
# WAFFLE_CREATE_MISSING_FLAGS WAFFLE_CREATE_MISSING_FLAGS = False
# The model that will be used to keep track of flags. Extends AbstractUserFlag.
WAFFLE_FLAG_MODEL = "registrar.WaffleFlag"
# endregion # endregion

View file

@ -0,0 +1,41 @@
# Generated by Django 4.2.10 on 2024-04-30 16:25
from django.conf import settings
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
('registrar', '0089_user_verification_type copy'),
]
operations = [
migrations.CreateModel(
name='WaffleFlag',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(help_text='The human/computer readable name.', max_length=100, unique=True, verbose_name='Name')),
('everyone', models.BooleanField(blank=True, help_text='Flip this flag on (Yes) or off (No) for everyone, overriding all other settings. Leave as Unknown to use normally.', null=True, verbose_name='Everyone')),
('percent', models.DecimalField(blank=True, decimal_places=1, help_text='A number between 0.0 and 99.9 to indicate a percentage of users for whom this flag will be active.', max_digits=3, null=True, verbose_name='Percent')),
('testing', models.BooleanField(default=False, help_text='Allow this flag to be set for a session for user testing', verbose_name='Testing')),
('superusers', models.BooleanField(default=True, help_text='Flag always active for superusers?', verbose_name='Superusers')),
('staff', models.BooleanField(default=False, help_text='Flag always active for staff?', verbose_name='Staff')),
('authenticated', models.BooleanField(default=False, help_text='Flag always active for authenticated users?', verbose_name='Authenticated')),
('languages', models.TextField(blank=True, default='', help_text='Activate this flag for users with one of these languages (comma-separated list)', verbose_name='Languages')),
('rollout', models.BooleanField(default=False, help_text='Activate roll-out mode?', verbose_name='Rollout')),
('note', models.TextField(blank=True, help_text='Note where this Flag is used.', verbose_name='Note')),
('created', models.DateTimeField(db_index=True, default=django.utils.timezone.now, help_text='Date when this Flag was created.', verbose_name='Created')),
('modified', models.DateTimeField(default=django.utils.timezone.now, help_text='Date when this Flag was last modified.', verbose_name='Modified')),
('groups', models.ManyToManyField(blank=True, help_text='Activate this flag for these user groups.', to='auth.group', verbose_name='Groups')),
('users', models.ManyToManyField(blank=True, help_text='Activate this flag for these users.', to=settings.AUTH_USER_MODEL, verbose_name='Users')),
],
options={
'verbose_name': 'Flag',
'verbose_name_plural': 'Flags',
'abstract': False,
},
),
]

View file

@ -15,6 +15,7 @@ from .user_group import UserGroup
from .website import Website from .website import Website
from .transition_domain import TransitionDomain from .transition_domain import TransitionDomain
from .verified_by_staff import VerifiedByStaff from .verified_by_staff import VerifiedByStaff
from .waffle_flag import WaffleFlag
__all__ = [ __all__ = [
"Contact", "Contact",
@ -33,6 +34,7 @@ __all__ = [
"Website", "Website",
"TransitionDomain", "TransitionDomain",
"VerifiedByStaff", "VerifiedByStaff",
"WaffleFlag",
] ]
auditlog.register(Contact) auditlog.register(Contact)
@ -51,3 +53,4 @@ auditlog.register(UserGroup, m2m_fields=["permissions"])
auditlog.register(Website) auditlog.register(Website)
auditlog.register(TransitionDomain) auditlog.register(TransitionDomain)
auditlog.register(VerifiedByStaff) auditlog.register(VerifiedByStaff)
auditlog.register(WaffleFlag)

View file

@ -0,0 +1,37 @@
from waffle.models import AbstractUserFlag
import logging
logger = logging.getLogger(__name__)
class WaffleFlag(AbstractUserFlag):
"""
Custom implementation of django-waffles 'Flag' object.
Read more here: https://waffle.readthedocs.io/en/stable/types/flag.html
Use this class when dealing with feature flags, such as profile_feature.
"""
class Meta:
"""Contains meta information about this class"""
verbose_name = "waffle flag"
verbose_name_plural = "Waffle flags"
@classmethod
def create_waffle_flags(cls):
"""
Creates a pre-defined list of flags for our migrations.
"""
logger.info("Creating default waffle flags...")
try:
# Flags can be activated through the command line or through django admin.
# To keep the scope of this function minimal and simple, if we require additional
# config on these flag, it should be done in a seperate function or as a command.
flag_names = [
"profile_feature",
"dns_hosting_feature",
]
flags = [cls(name=flag_name) for flag_name in flag_names]
cls.objects.bulk_create(flags)
except Exception as e:
logger.error(f"An error occurred when attempting to create WaffleFlags: {e}")

View file

@ -72,7 +72,7 @@
{% if not IS_PRODUCTION %} {% if not IS_PRODUCTION %}
{% include "includes/non-production-alert.html" %} {% include "includes/non-production-alert.html" %}
{% if profile_feature_flag %} {% if has_profile_feature_flag %}
<h2>it worked!</h2> <h2>it worked!</h2>
{% endif %} {% endif %}
{% endif %} {% endif %}

View file

@ -22,7 +22,7 @@ def index(request):
# This is a django waffle flag which toggles features based off of the "flag" table # This is a django waffle flag which toggles features based off of the "flag" table
# TODO - note that the flag must be checked for superuser AND staff for superuser to see it # TODO - note that the flag must be checked for superuser AND staff for superuser to see it
context["profile_feature_flag"] = flag_is_active(request, "profile_feature") context["has_profile_feature_flag"] = flag_is_active(request, "profile_feature")
# If they can delete domain requests, add the delete button to the context # If they can delete domain requests, add the delete button to the context
if has_deletable_domain_requests: if has_deletable_domain_requests: