mirror of
https://github.com/zulip/zulip.git
synced 2025-10-28 10:33:54 +00:00
Previously, we do not allow mentioning system user groups at all. Now we want to use silent mention syntax for system groups in the message sent when updating the posting permission for a stream, so it is important to allowing silent mentioning system groups at least. And there is no problem in allowing silent mentions of system groups for all users. We do not allow mentioning system groups as can_mention_group for them is set to "Nobody" group.
189 lines
7.5 KiB
Python
189 lines
7.5 KiB
Python
from django.db import models
|
|
from django.db.models import CASCADE
|
|
from django.utils.timezone import now as timezone_now
|
|
from django.utils.translation import gettext_lazy
|
|
from django_cte import CTEManager
|
|
|
|
from zerver.lib.types import GroupPermissionSetting
|
|
from zerver.models.users import UserProfile
|
|
|
|
|
|
class SystemGroups:
|
|
FULL_MEMBERS = "role:fullmembers"
|
|
EVERYONE_ON_INTERNET = "role:internet"
|
|
OWNERS = "role:owners"
|
|
ADMINISTRATORS = "role:administrators"
|
|
MODERATORS = "role:moderators"
|
|
MEMBERS = "role:members"
|
|
EVERYONE = "role:everyone"
|
|
NOBODY = "role:nobody"
|
|
|
|
GROUP_DISPLAY_NAME_MAP = {
|
|
NOBODY: gettext_lazy("Nobody"),
|
|
OWNERS: gettext_lazy("Owners"),
|
|
ADMINISTRATORS: gettext_lazy("Administrators"),
|
|
MODERATORS: gettext_lazy("Moderators"),
|
|
FULL_MEMBERS: gettext_lazy("Full members"),
|
|
MEMBERS: gettext_lazy("Members"),
|
|
EVERYONE: gettext_lazy("Everyone"),
|
|
EVERYONE_ON_INTERNET: gettext_lazy("Everyone on the internet"),
|
|
}
|
|
|
|
|
|
class UserGroup(models.Model): # type: ignore[django-manager-missing] # django-stubs cannot resolve the custom CTEManager yet https://github.com/typeddjango/django-stubs/issues/1023
|
|
objects: CTEManager = CTEManager()
|
|
direct_members = models.ManyToManyField(
|
|
UserProfile, through="zerver.UserGroupMembership", related_name="direct_groups"
|
|
)
|
|
direct_subgroups = models.ManyToManyField(
|
|
"zerver.NamedUserGroup",
|
|
symmetrical=False,
|
|
through="zerver.GroupGroupMembership",
|
|
through_fields=("supergroup", "subgroup"),
|
|
related_name="direct_supergroups",
|
|
)
|
|
realm = models.ForeignKey("zerver.Realm", on_delete=CASCADE)
|
|
|
|
|
|
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
|
|
INVALID_NAME_PREFIXES = ["@", "role:", "user:", "stream:", "channel:"]
|
|
|
|
# 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",
|
|
)
|
|
name = models.CharField(max_length=MAX_NAME_LENGTH, db_column="name")
|
|
description = models.TextField(default="", db_column="description")
|
|
date_created = models.DateTimeField(default=timezone_now, null=True)
|
|
creator = models.ForeignKey(
|
|
UserProfile, null=True, on_delete=models.SET_NULL, related_name="+", db_column="creator_id"
|
|
)
|
|
is_system_group = models.BooleanField(default=False, db_column="is_system_group")
|
|
|
|
can_add_members_group = models.ForeignKey(
|
|
UserGroup, on_delete=models.RESTRICT, related_name="+"
|
|
)
|
|
can_join_group = models.ForeignKey(UserGroup, on_delete=models.RESTRICT, related_name="+")
|
|
can_leave_group = models.ForeignKey(UserGroup, on_delete=models.RESTRICT, related_name="+")
|
|
can_manage_group = models.ForeignKey(UserGroup, on_delete=models.RESTRICT, related_name="+")
|
|
can_mention_group = models.ForeignKey(
|
|
UserGroup, on_delete=models.RESTRICT, db_column="can_mention_group_id"
|
|
)
|
|
can_remove_members_group = models.ForeignKey(
|
|
UserGroup, on_delete=models.RESTRICT, related_name="+"
|
|
)
|
|
|
|
realm_for_sharding = models.ForeignKey("zerver.Realm", on_delete=CASCADE, db_column="realm_id")
|
|
deactivated = models.BooleanField(default=False, db_default=False)
|
|
|
|
# We do not have "Full members" and "Everyone on the internet"
|
|
# group here since there isn't a separate role value for full
|
|
# members and spectators.
|
|
SYSTEM_USER_GROUP_ROLE_MAP = {
|
|
UserProfile.ROLE_REALM_OWNER: {
|
|
"name": SystemGroups.OWNERS,
|
|
"description": "Owners of this organization",
|
|
},
|
|
UserProfile.ROLE_REALM_ADMINISTRATOR: {
|
|
"name": SystemGroups.ADMINISTRATORS,
|
|
"description": "Administrators of this organization, including owners",
|
|
},
|
|
UserProfile.ROLE_MODERATOR: {
|
|
"name": SystemGroups.MODERATORS,
|
|
"description": "Moderators of this organization, including administrators",
|
|
},
|
|
UserProfile.ROLE_MEMBER: {
|
|
"name": SystemGroups.MEMBERS,
|
|
"description": "Members of this organization, not including guests",
|
|
},
|
|
UserProfile.ROLE_GUEST: {
|
|
"name": SystemGroups.EVERYONE,
|
|
"description": "Everyone in this organization, including guests",
|
|
},
|
|
}
|
|
|
|
GROUP_PERMISSION_SETTINGS = {
|
|
"can_add_members_group": GroupPermissionSetting(
|
|
require_system_group=False,
|
|
allow_internet_group=False,
|
|
allow_nobody_group=True,
|
|
allow_everyone_group=False,
|
|
default_group_name="group_creator",
|
|
default_for_system_groups=SystemGroups.NOBODY,
|
|
),
|
|
"can_join_group": GroupPermissionSetting(
|
|
require_system_group=False,
|
|
allow_internet_group=False,
|
|
allow_nobody_group=True,
|
|
allow_everyone_group=False,
|
|
default_group_name=SystemGroups.NOBODY,
|
|
default_for_system_groups=SystemGroups.NOBODY,
|
|
),
|
|
"can_leave_group": GroupPermissionSetting(
|
|
require_system_group=False,
|
|
allow_internet_group=False,
|
|
allow_nobody_group=True,
|
|
allow_everyone_group=True,
|
|
default_group_name=SystemGroups.EVERYONE,
|
|
default_for_system_groups=SystemGroups.NOBODY,
|
|
),
|
|
"can_manage_group": GroupPermissionSetting(
|
|
require_system_group=False,
|
|
allow_internet_group=False,
|
|
allow_nobody_group=True,
|
|
allow_everyone_group=False,
|
|
default_group_name="group_creator",
|
|
default_for_system_groups=SystemGroups.NOBODY,
|
|
),
|
|
"can_mention_group": GroupPermissionSetting(
|
|
require_system_group=False,
|
|
allow_internet_group=False,
|
|
allow_nobody_group=True,
|
|
allow_everyone_group=True,
|
|
default_group_name=SystemGroups.EVERYONE,
|
|
default_for_system_groups=SystemGroups.NOBODY,
|
|
),
|
|
"can_remove_members_group": GroupPermissionSetting(
|
|
require_system_group=False,
|
|
allow_internet_group=False,
|
|
allow_nobody_group=True,
|
|
allow_everyone_group=False,
|
|
default_group_name=SystemGroups.NOBODY,
|
|
default_for_system_groups=SystemGroups.NOBODY,
|
|
),
|
|
}
|
|
|
|
class Meta:
|
|
unique_together = (("realm_for_sharding", "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="+")
|
|
|
|
class Meta:
|
|
unique_together = (("user_group", "user_profile"),)
|
|
|
|
|
|
class GroupGroupMembership(models.Model):
|
|
supergroup = models.ForeignKey(UserGroup, on_delete=CASCADE, related_name="+")
|
|
subgroup = models.ForeignKey(NamedUserGroup, on_delete=CASCADE, related_name="+")
|
|
|
|
class Meta:
|
|
constraints = [
|
|
models.UniqueConstraint(
|
|
fields=["supergroup", "subgroup"], name="zerver_groupgroupmembership_uniq"
|
|
)
|
|
]
|