mirror of
https://github.com/cisagov/manage.get.gov.git
synced 2025-05-19 19:09:22 +02:00
Migrations, etc
This commit is contained in:
parent
f52a7e08fe
commit
5e2ec5d1c8
8 changed files with 103 additions and 4 deletions
|
@ -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)
|
|
@ -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
|
||||||
|
|
||||||
|
|
41
src/registrar/migrations/0090_waffleflag.py
Normal file
41
src/registrar/migrations/0090_waffleflag.py
Normal 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,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -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)
|
37
src/registrar/models/waffle_flag.py
Normal file
37
src/registrar/models/waffle_flag.py
Normal 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}")
|
|
@ -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 %}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue