diff --git a/zerver/lib/export.py b/zerver/lib/export.py index 08ecd64b2e..d5387efddd 100644 --- a/zerver/lib/export.py +++ b/zerver/lib/export.py @@ -137,6 +137,7 @@ ALL_ZULIP_TABLES = { "zerver_missedmessageemailaddress", "zerver_multiuseinvite", "zerver_multiuseinvite_streams", + "zerver_namedusergroup", "zerver_onboardingstep", "zerver_preregistrationrealm", "zerver_preregistrationuser", @@ -243,6 +244,8 @@ NON_EXPORTED_TABLES = { "zerver_submessage", # Drafts don't need to be exported as they are supposed to be more ephemeral. "zerver_draft", + # NamedUserGroup is not exported temporarily, will be done in the next few commits. + "zerver_namedusergroup", # For any tables listed below here, it's a bug that they are not present in the export. } diff --git a/zerver/migrations/0512_namedusergroup.py b/zerver/migrations/0512_namedusergroup.py new file mode 100644 index 0000000000..6240f64429 --- /dev/null +++ b/zerver/migrations/0512_namedusergroup.py @@ -0,0 +1,56 @@ +# Generated by Django 4.2.12 on 2024-04-19 03:44 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("zerver", "0511_stream_creator"), + ] + + operations = [ + migrations.CreateModel( + name="NamedUserGroup", + fields=[ + ( + "usergroup_ptr", + models.OneToOneField( + auto_created=True, + on_delete=django.db.models.deletion.CASCADE, + parent_link=True, + primary_key=True, + related_name="named_user_group", + serialize=False, + to="zerver.usergroup", + ), + ), + ("named_group_name", models.CharField(db_column="name", max_length=100)), + ("named_group_description", models.TextField(db_column="description", default="")), + ( + "named_group_is_system_group", + models.BooleanField(db_column="is_system_group", default=False), + ), + ( + "named_group_can_mention_group", + models.ForeignKey( + db_column="can_mention_group_id", + on_delete=django.db.models.deletion.RESTRICT, + to="zerver.usergroup", + ), + ), + ( + "realm_for_sharding", + models.ForeignKey( + db_column="realm_id", + on_delete=django.db.models.deletion.CASCADE, + to="zerver.realm", + ), + ), + ], + options={ + "unique_together": {("realm_for_sharding", "named_group_name")}, + }, + bases=("zerver.usergroup",), + ), + ] diff --git a/zerver/models/groups.py b/zerver/models/groups.py index eeaf0759db..1ca99eba9a 100644 --- a/zerver/models/groups.py +++ b/zerver/models/groups.py @@ -82,6 +82,37 @@ class UserGroup(models.Model): # type: ignore[django-manager-missing] # django- unique_together = (("realm", "name"),) +class NamedUserGroup(UserGroup): # type: ignore[django-manager-missing] # django-stubs cannot resolve the custom CTEManager yet https://github.com/typeddjango/django-stubs/issues/1023 + MAX_NAME_LENGTH = 100 + + # This field is automatically created by django, but we still need + # to add this here to keep mypy happy when accessing usergroup_ptr. + usergroup_ptr = models.OneToOneField( + auto_created=True, + on_delete=CASCADE, + parent_link=True, + primary_key=True, + serialize=False, + to=UserGroup, + # We are not using the auto-generated name here to avoid + # duplicate backward relation name because "can_mention_group" + # setting also points to a UserGroup object. + related_name="named_user_group", + ) + named_group_name = models.CharField(max_length=MAX_NAME_LENGTH, db_column="name") + named_group_description = models.TextField(default="", db_column="description") + named_group_is_system_group = models.BooleanField(default=False, db_column="is_system_group") + + named_group_can_mention_group = models.ForeignKey( + UserGroup, on_delete=models.RESTRICT, db_column="can_mention_group_id" + ) + + realm_for_sharding = models.ForeignKey("zerver.Realm", on_delete=CASCADE, db_column="realm_id") + + class Meta: + unique_together = (("realm_for_sharding", "named_group_name"),) + + class UserGroupMembership(models.Model): user_group = models.ForeignKey(UserGroup, on_delete=CASCADE, related_name="+") user_profile = models.ForeignKey(UserProfile, on_delete=CASCADE, related_name="+")