Refactor read only group creation as post migrate operation

This commit is contained in:
Christopher C. Wells 2023-02-11 10:31:14 -08:00
parent 996d81966c
commit 10a58e61b5
10 changed files with 86 additions and 80 deletions

View File

@ -2,10 +2,18 @@
import os
from django.apps import AppConfig
from django.conf import settings
from django.db.models.signals import post_migrate
from babybuddy import VERSION
def create_read_only_group(sender, **kwargs):
from django.contrib.auth.models import Group
Group.objects.get_or_create(name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"])
class BabyBuddyConfig(AppConfig):
name = "babybuddy"
verbose_name = "Baby Buddy"
@ -16,3 +24,4 @@ class BabyBuddyConfig(AppConfig):
if os.path.isfile(".git/refs/heads/master"):
commit = open(".git/refs/heads/master").read()
self.version_string += " ({})".format(commit[0:7])
post_migrate.connect(create_read_only_group, sender=self)

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from django import forms
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import PasswordChangeForm, UserCreationForm
from django.contrib.auth.models import Group
@ -31,7 +32,11 @@ class BabyBuddyUserForm(forms.ModelForm):
user = kwargs["instance"]
if user:
kwargs["initial"].update(
{"is_read_only": user.groups.filter(name="read_only").exists()}
{
"is_read_only": user.groups.filter(
name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"]
).exists()
}
)
super(BabyBuddyUserForm, self).__init__(*args, **kwargs)
@ -44,7 +49,9 @@ class BabyBuddyUserForm(forms.ModelForm):
user.is_superuser = True
if commit:
user.save()
readonly_group = Group.objects.get(name="read_only")
readonly_group = Group.objects.get(
name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"]
)
if is_read_only:
user.groups.add(readonly_group.id)
else:

View File

@ -11,6 +11,7 @@ Example usage:
import sys
import getpass
from django.conf import settings
from django.contrib.auth import get_user_model, models
from django.contrib.auth.password_validation import validate_password
from django.core import exceptions
@ -119,7 +120,9 @@ class Command(BaseCommand):
if is_read_only:
user.is_superuser = False
user.save()
group = models.Group.objects.get(name="read_only")
group = models.Group.objects.get(
name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"]
)
user.groups.add(group)
else:
user.is_superuser = True

View File

@ -1,72 +1,6 @@
# Generated by Django 4.1.2 on 2022-10-23 08:21
from django.db import migrations
from django.contrib.auth.models import Group, Permission
import logging
logger = logging.getLogger(__name__)
# MODELS = [model.__name__ for model in apps.get_models()]
MODELS = [
"Tag",
"tagged",
"BMI",
"Child",
"Diaper Change",
"Feeding",
"Head Circumference",
"Height",
"Note",
"Pumping",
"Sleep",
"Temperature",
"Timer",
"Tummy Time",
"Weight",
"user",
]
PERMISSIONS = ["add", "change", "delete", "view"]
def add_group_permissions(apps, schema_editor):
group, created = Group.objects.get_or_create(name="read_only")
perm = []
for model in MODELS:
name = f"Can view {model}"
logging.info(f"Creating {name}...")
try:
perm.append(Permission.objects.get(name=name))
except Permission.DoesNotExist:
logging.warning(f"Permission not found with name {name}.")
continue
group.permissions.add(*perm)
group, created = Group.objects.get_or_create(name="standard")
perm = []
for model in MODELS:
for permission in PERMISSIONS:
name = f"Can {permission} {model}"
logging.info(f"Creating {name}...")
try:
perm.append(Permission.objects.get(name=name))
except Permission.DoesNotExist:
logging.warning(f"Permission not found with name {name}.")
continue
group.permissions.add(*perm)
def revert_migration(apps, schema_editor):
Group.objects.filter(
name__in=[
"read_only",
"standard",
]
).delete()
class Migration(migrations.Migration):
@ -74,4 +8,5 @@ class Migration(migrations.Migration):
("babybuddy", "0023_alter_settings_timezone"),
]
operations = [migrations.RunPython(add_group_permissions, revert_migration)]
# Migration removed in favor of post migrate handling in core.apps.CoreConfig.
operations = []

View File

@ -24,8 +24,8 @@ DEBUG = bool(strtobool(os.environ.get("DEBUG") or "False"))
INSTALLED_APPS = [
"api",
"babybuddy",
"core",
"babybuddy.apps.BabyBuddyConfig",
"core.apps.CoreConfig",
"dashboard",
"reports",
"axes",
@ -356,7 +356,8 @@ DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
# See README.md#configuration for details about these settings.
BABY_BUDDY = {
"NAP_START_MIN": os.environ.get("NAP_START_MIN") or "06:00",
"NAP_START_MAX": os.environ.get("NAP_START_MAX") or "18:00",
"ALLOW_UPLOADS": bool(strtobool(os.environ.get("ALLOW_UPLOADS") or "True")),
"NAP_START_MAX": os.environ.get("NAP_START_MAX") or "18:00",
"NAP_START_MIN": os.environ.get("NAP_START_MIN") or "06:00",
"READ_ONLY_GROUP_NAME": "read_only",
}

View File

@ -2,6 +2,7 @@
from django import template
from django.apps import apps
from django.conf import settings
from django.utils import timezone
from django.utils.translation import to_locale, get_language
@ -80,4 +81,4 @@ def user_is_locked(user):
@register.simple_tag()
def user_is_read_only(user):
return user.groups.filter(name="read_only").exists()
return user.groups.filter(name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"]).exists()

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from django.test import TransactionTestCase
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.management import call_command
@ -28,6 +29,7 @@ class CommandsTestCase(TransactionTestCase):
self.assertEqual(Child.objects.count(), 1)
def test_createuser(self):
call_command("migrate", verbosity=0)
call_command(
"createuser",
username="regularuser",
@ -66,4 +68,8 @@ class CommandsTestCase(TransactionTestCase):
self.assertIsInstance(user, get_user_model())
self.assertFalse(user.is_superuser)
self.assertFalse(user.is_staff)
self.assertTrue(user.groups.filter(name="read_only").exists())
self.assertTrue(
user.groups.filter(
name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"]
).exists()
)

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import datetime
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.management import call_command
from django.test import Client as HttpClient, override_settings, TestCase
@ -117,7 +118,11 @@ class FormsTestCase(TestCase):
self.assertIsInstance(user, get_user_model())
self.assertTrue(user.is_superuser)
self.assertFalse(user.is_staff)
self.assertFalse(user.groups.filter(name="read_only").exists())
self.assertFalse(
user.groups.filter(
name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"]
).exists()
)
def test_add_staff_user(self):
self.user.is_staff = True
@ -133,7 +138,11 @@ class FormsTestCase(TestCase):
self.assertIsInstance(user, get_user_model())
self.assertTrue(user.is_superuser)
self.assertTrue(user.is_staff)
self.assertFalse(user.groups.filter(name="read_only").exists())
self.assertFalse(
user.groups.filter(
name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"]
).exists()
)
def test_add_read_only_user(self):
self.user.is_staff = True
@ -149,7 +158,11 @@ class FormsTestCase(TestCase):
self.assertIsInstance(user, get_user_model())
self.assertFalse(user.is_superuser)
self.assertFalse(user.is_staff)
self.assertTrue(user.groups.filter(name="read_only").exists())
self.assertTrue(
user.groups.filter(
name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"]
).exists()
)
def test_user_settings(self):
self.c.login(**self.credentials)

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
from django.conf import settings
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.test import TestCase
@ -26,6 +27,6 @@ class TemplateTagsTestCase(TestCase):
)
self.assertFalse(babybuddy.user_is_read_only(user))
group = Group.objects.get(name="read_only")
group = Group.objects.get(name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"])
user.groups.add(group)
self.assertTrue(babybuddy.user_is_read_only(user))

30
core/apps.py Normal file
View File

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
from django.apps import AppConfig
from django.conf import settings
from django.db.models.signals import post_migrate
def add_read_only_group_permissions(sender, **kwargs):
from django.apps import apps
from django.contrib.auth.models import Group, Permission
permissions = []
for model in apps.all_models["core"]:
try:
permissions.append(Permission.objects.get(codename=f"view_{model}"))
except Permission.DoesNotExist:
continue
if len(permissions) > 0:
try:
group = Group.objects.get(name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"])
group.permissions.add(*permissions)
except Group.DoesNotExist:
pass
class CoreConfig(AppConfig):
name = "core"
def ready(self):
post_migrate.connect(add_read_only_group_permissions, sender=self)