mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	This commit adds a RealmAuditLog entry for when someone deletes an export. This helps to track the acting_user.
		
			
				
	
	
		
			281 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			281 lines
		
	
	
		
			9.9 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from enum import IntEnum, unique
 | 
						|
 | 
						|
from django.core.serializers.json import DjangoJSONEncoder
 | 
						|
from django.db import models
 | 
						|
from django.db.models import CASCADE, Q
 | 
						|
from typing_extensions import override
 | 
						|
 | 
						|
from zerver.models.groups import NamedUserGroup
 | 
						|
from zerver.models.realms import Realm
 | 
						|
from zerver.models.streams import Stream
 | 
						|
from zerver.models.users import UserProfile
 | 
						|
 | 
						|
 | 
						|
@unique
 | 
						|
class AuditLogEventType(IntEnum):
 | 
						|
    USER_CREATED = 101
 | 
						|
    USER_ACTIVATED = 102
 | 
						|
    USER_DEACTIVATED = 103
 | 
						|
    USER_REACTIVATED = 104
 | 
						|
    USER_ROLE_CHANGED = 105
 | 
						|
    USER_DELETED = 106
 | 
						|
    USER_DELETED_PRESERVING_MESSAGES = 107
 | 
						|
    USER_SPECIAL_PERMISSION_CHANGED = 108
 | 
						|
 | 
						|
    USER_SOFT_ACTIVATED = 120
 | 
						|
    USER_SOFT_DEACTIVATED = 121
 | 
						|
    USER_PASSWORD_CHANGED = 122
 | 
						|
    USER_AVATAR_SOURCE_CHANGED = 123
 | 
						|
    USER_FULL_NAME_CHANGED = 124
 | 
						|
    USER_EMAIL_CHANGED = 125
 | 
						|
    USER_TERMS_OF_SERVICE_VERSION_CHANGED = 126
 | 
						|
    USER_API_KEY_CHANGED = 127
 | 
						|
    USER_BOT_OWNER_CHANGED = 128
 | 
						|
    USER_DEFAULT_SENDING_STREAM_CHANGED = 129
 | 
						|
    USER_DEFAULT_REGISTER_STREAM_CHANGED = 130
 | 
						|
    USER_DEFAULT_ALL_PUBLIC_STREAMS_CHANGED = 131
 | 
						|
    USER_SETTING_CHANGED = 132
 | 
						|
    USER_DIGEST_EMAIL_CREATED = 133
 | 
						|
 | 
						|
    REALM_DEACTIVATED = 201
 | 
						|
    REALM_REACTIVATED = 202
 | 
						|
    REALM_SCRUBBED = 203
 | 
						|
    REALM_PLAN_TYPE_CHANGED = 204
 | 
						|
    REALM_LOGO_CHANGED = 205
 | 
						|
    REALM_EXPORTED = 206
 | 
						|
    REALM_PROPERTY_CHANGED = 207
 | 
						|
    REALM_ICON_SOURCE_CHANGED = 208
 | 
						|
    REALM_DISCOUNT_CHANGED = 209
 | 
						|
    REALM_SPONSORSHIP_APPROVED = 210
 | 
						|
    REALM_BILLING_MODALITY_CHANGED = 211
 | 
						|
    REALM_REACTIVATION_EMAIL_SENT = 212
 | 
						|
    REALM_SPONSORSHIP_PENDING_STATUS_CHANGED = 213
 | 
						|
    REALM_SUBDOMAIN_CHANGED = 214
 | 
						|
    REALM_CREATED = 215
 | 
						|
    REALM_DEFAULT_USER_SETTINGS_CHANGED = 216
 | 
						|
    REALM_ORG_TYPE_CHANGED = 217
 | 
						|
    REALM_DOMAIN_ADDED = 218
 | 
						|
    REALM_DOMAIN_CHANGED = 219
 | 
						|
    REALM_DOMAIN_REMOVED = 220
 | 
						|
    REALM_PLAYGROUND_ADDED = 221
 | 
						|
    REALM_PLAYGROUND_REMOVED = 222
 | 
						|
    REALM_LINKIFIER_ADDED = 223
 | 
						|
    REALM_LINKIFIER_CHANGED = 224
 | 
						|
    REALM_LINKIFIER_REMOVED = 225
 | 
						|
    REALM_EMOJI_ADDED = 226
 | 
						|
    REALM_EMOJI_REMOVED = 227
 | 
						|
    REALM_LINKIFIERS_REORDERED = 228
 | 
						|
    REALM_IMPORTED = 229
 | 
						|
    REALM_EXPORT_DELETED = 230
 | 
						|
 | 
						|
    SUBSCRIPTION_CREATED = 301
 | 
						|
    SUBSCRIPTION_ACTIVATED = 302
 | 
						|
    SUBSCRIPTION_DEACTIVATED = 303
 | 
						|
    SUBSCRIPTION_PROPERTY_CHANGED = 304
 | 
						|
 | 
						|
    USER_MUTED = 350
 | 
						|
    USER_UNMUTED = 351
 | 
						|
 | 
						|
    STRIPE_CUSTOMER_CREATED = 401
 | 
						|
    STRIPE_CARD_CHANGED = 402
 | 
						|
    STRIPE_PLAN_CHANGED = 403
 | 
						|
    STRIPE_PLAN_QUANTITY_RESET = 404
 | 
						|
 | 
						|
    CUSTOMER_CREATED = 501
 | 
						|
    CUSTOMER_PLAN_CREATED = 502
 | 
						|
    CUSTOMER_SWITCHED_FROM_MONTHLY_TO_ANNUAL_PLAN = 503
 | 
						|
    CUSTOMER_SWITCHED_FROM_ANNUAL_TO_MONTHLY_PLAN = 504
 | 
						|
    CUSTOMER_PROPERTY_CHANGED = 505
 | 
						|
    CUSTOMER_PLAN_PROPERTY_CHANGED = 506
 | 
						|
 | 
						|
    CHANNEL_CREATED = 601
 | 
						|
    CHANNEL_DEACTIVATED = 602
 | 
						|
    CHANNEL_NAME_CHANGED = 603
 | 
						|
    CHANNEL_REACTIVATED = 604
 | 
						|
    CHANNEL_MESSAGE_RETENTION_DAYS_CHANGED = 605
 | 
						|
    CHANNEL_PROPERTY_CHANGED = 607
 | 
						|
    CHANNEL_GROUP_BASED_SETTING_CHANGED = 608
 | 
						|
 | 
						|
    USER_GROUP_CREATED = 701
 | 
						|
    USER_GROUP_DELETED = 702
 | 
						|
    USER_GROUP_DIRECT_USER_MEMBERSHIP_ADDED = 703
 | 
						|
    USER_GROUP_DIRECT_USER_MEMBERSHIP_REMOVED = 704
 | 
						|
    USER_GROUP_DIRECT_SUBGROUP_MEMBERSHIP_ADDED = 705
 | 
						|
    USER_GROUP_DIRECT_SUBGROUP_MEMBERSHIP_REMOVED = 706
 | 
						|
    USER_GROUP_DIRECT_SUPERGROUP_MEMBERSHIP_ADDED = 707
 | 
						|
    USER_GROUP_DIRECT_SUPERGROUP_MEMBERSHIP_REMOVED = 708
 | 
						|
    # 709 to 719 reserved for membership changes
 | 
						|
    USER_GROUP_NAME_CHANGED = 720
 | 
						|
    USER_GROUP_DESCRIPTION_CHANGED = 721
 | 
						|
    USER_GROUP_GROUP_BASED_SETTING_CHANGED = 722
 | 
						|
    USER_GROUP_DEACTIVATED = 723
 | 
						|
 | 
						|
    SAVED_SNIPPET_CREATED = 800
 | 
						|
 | 
						|
    # The following values are only for remote server/realm logs.
 | 
						|
    # Values should be exactly 10000 greater than the corresponding
 | 
						|
    # value used for the same purpose in realm audit logs (e.g.,
 | 
						|
    # REALM_DEACTIVATED = 201, and REMOTE_SERVER_DEACTIVATED = 10201).
 | 
						|
    REMOTE_SERVER_DEACTIVATED = 10201
 | 
						|
    REMOTE_SERVER_REACTIVATED = 10202
 | 
						|
    REMOTE_SERVER_PLAN_TYPE_CHANGED = 10204
 | 
						|
    REMOTE_SERVER_DISCOUNT_CHANGED = 10209
 | 
						|
    REMOTE_SERVER_SPONSORSHIP_APPROVED = 10210
 | 
						|
    REMOTE_SERVER_BILLING_MODALITY_CHANGED = 10211
 | 
						|
    REMOTE_SERVER_SPONSORSHIP_PENDING_STATUS_CHANGED = 10213
 | 
						|
    REMOTE_SERVER_CREATED = 10215
 | 
						|
 | 
						|
    # This value is for RemoteRealmAuditLog entries tracking changes to the
 | 
						|
    # RemoteRealm model resulting from modified realm information sent to us
 | 
						|
    # via send_server_data_to_push_bouncer.
 | 
						|
    REMOTE_REALM_VALUE_UPDATED = 20001
 | 
						|
    REMOTE_PLAN_TRANSFERRED_SERVER_TO_REALM = 20002
 | 
						|
    REMOTE_REALM_LOCALLY_DELETED = 20003
 | 
						|
    REMOTE_REALM_LOCALLY_DELETED_RESTORED = 20004
 | 
						|
 | 
						|
 | 
						|
class AbstractRealmAuditLog(models.Model):
 | 
						|
    """Defines fields common to RealmAuditLog and RemoteRealmAuditLog."""
 | 
						|
 | 
						|
    event_time = models.DateTimeField(db_index=True)
 | 
						|
    # If True, event_time is an overestimate of the true time. Can be used
 | 
						|
    # by migrations when introducing a new event_type.
 | 
						|
    backfilled = models.BooleanField(default=False)
 | 
						|
 | 
						|
    # Keys within extra_data, when extra_data is a json dict. Keys are strings because
 | 
						|
    # json keys must always be strings.
 | 
						|
    OLD_VALUE = "1"
 | 
						|
    NEW_VALUE = "2"
 | 
						|
    ROLE_COUNT = "10"
 | 
						|
    ROLE_COUNT_HUMANS = "11"
 | 
						|
    ROLE_COUNT_BOTS = "12"
 | 
						|
 | 
						|
    extra_data = models.JSONField(default=dict, encoder=DjangoJSONEncoder)
 | 
						|
 | 
						|
    # See AuditLogEventType class above.
 | 
						|
    event_type = models.PositiveSmallIntegerField()
 | 
						|
 | 
						|
    # event_types synced from on-prem installations to Zulip Cloud when
 | 
						|
    # billing for mobile push notifications is enabled.  Every billing
 | 
						|
    # event_type should have ROLE_COUNT populated in extra_data.
 | 
						|
    SYNCED_BILLING_EVENTS = [
 | 
						|
        AuditLogEventType.USER_CREATED,
 | 
						|
        AuditLogEventType.USER_ACTIVATED,
 | 
						|
        AuditLogEventType.USER_DEACTIVATED,
 | 
						|
        AuditLogEventType.USER_REACTIVATED,
 | 
						|
        AuditLogEventType.USER_ROLE_CHANGED,
 | 
						|
        AuditLogEventType.REALM_DEACTIVATED,
 | 
						|
        AuditLogEventType.REALM_REACTIVATED,
 | 
						|
        AuditLogEventType.REALM_IMPORTED,
 | 
						|
    ]
 | 
						|
 | 
						|
    HOW_REALM_CREATOR_FOUND_ZULIP_OPTIONS = {
 | 
						|
        "existing_user": "At an organization that's using it",
 | 
						|
        "search_engine": "Search engine",
 | 
						|
        "review_site": "Review site",
 | 
						|
        "personal_recommendation": "Personal recommendation",
 | 
						|
        "hacker_news": "Hacker News",
 | 
						|
        "reddit": "Reddit",
 | 
						|
        "ad": "Advertisement",
 | 
						|
        "other": "Other",
 | 
						|
        "forgot": "Don't remember",
 | 
						|
        "refuse_to_answer": "Prefer not to say",
 | 
						|
    }
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        abstract = True
 | 
						|
 | 
						|
 | 
						|
class RealmAuditLog(AbstractRealmAuditLog):
 | 
						|
    """
 | 
						|
    RealmAuditLog tracks important changes to users, streams, and
 | 
						|
    realms in Zulip.  It is intended to support both
 | 
						|
    debugging/introspection (e.g. determining when a user's left a
 | 
						|
    given stream?) as well as help with some database migrations where
 | 
						|
    we might be able to do a better data backfill with it.  Here are a
 | 
						|
    few key details about how this works:
 | 
						|
 | 
						|
    * acting_user is the user who initiated the state change
 | 
						|
    * modified_user (if present) is the user being modified
 | 
						|
    * modified_stream (if present) is the stream being modified
 | 
						|
    * modified_user_group (if present) is the user group being modified
 | 
						|
 | 
						|
    For example:
 | 
						|
    * When a user subscribes another user to a stream, modified_user,
 | 
						|
      acting_user, and modified_stream will all be present and different.
 | 
						|
    * When an administrator changes an organization's realm icon,
 | 
						|
      acting_user is that administrator and modified_user,
 | 
						|
      modified_stream and modified_user_group will be None.
 | 
						|
    """
 | 
						|
 | 
						|
    realm = models.ForeignKey(Realm, on_delete=CASCADE)
 | 
						|
    acting_user = models.ForeignKey(
 | 
						|
        UserProfile,
 | 
						|
        null=True,
 | 
						|
        related_name="+",
 | 
						|
        on_delete=CASCADE,
 | 
						|
    )
 | 
						|
    modified_user = models.ForeignKey(
 | 
						|
        UserProfile,
 | 
						|
        null=True,
 | 
						|
        related_name="+",
 | 
						|
        on_delete=CASCADE,
 | 
						|
    )
 | 
						|
    modified_stream = models.ForeignKey(
 | 
						|
        Stream,
 | 
						|
        null=True,
 | 
						|
        on_delete=CASCADE,
 | 
						|
    )
 | 
						|
    modified_user_group = models.ForeignKey(
 | 
						|
        NamedUserGroup,
 | 
						|
        null=True,
 | 
						|
        on_delete=CASCADE,
 | 
						|
    )
 | 
						|
    event_last_message_id = models.IntegerField(null=True)
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        ordering = ["id"]
 | 
						|
        indexes = [
 | 
						|
            models.Index(
 | 
						|
                name="zerver_realmauditlog_realm__event_type__event_time",
 | 
						|
                fields=["realm", "event_type", "event_time"],
 | 
						|
            ),
 | 
						|
            models.Index(
 | 
						|
                name="zerver_realmauditlog_user_subscriptions_idx",
 | 
						|
                fields=["modified_user", "modified_stream"],
 | 
						|
                condition=Q(
 | 
						|
                    event_type__in=[
 | 
						|
                        AuditLogEventType.SUBSCRIPTION_CREATED,
 | 
						|
                        AuditLogEventType.SUBSCRIPTION_ACTIVATED,
 | 
						|
                        AuditLogEventType.SUBSCRIPTION_DEACTIVATED,
 | 
						|
                    ]
 | 
						|
                ),
 | 
						|
            ),
 | 
						|
            models.Index(
 | 
						|
                # Used in analytics/lib/counts.py for computing active users for realm_active_humans
 | 
						|
                name="zerver_realmauditlog_user_activations_idx",
 | 
						|
                fields=["modified_user", "event_time"],
 | 
						|
                condition=Q(
 | 
						|
                    event_type__in=[
 | 
						|
                        AuditLogEventType.USER_CREATED,
 | 
						|
                        AuditLogEventType.USER_ACTIVATED,
 | 
						|
                        AuditLogEventType.USER_DEACTIVATED,
 | 
						|
                        AuditLogEventType.USER_REACTIVATED,
 | 
						|
                    ]
 | 
						|
                ),
 | 
						|
            ),
 | 
						|
        ]
 | 
						|
 | 
						|
    @override
 | 
						|
    def __str__(self) -> str:
 | 
						|
        event_type_name = AuditLogEventType(self.event_type).name
 | 
						|
        if self.modified_user is not None:
 | 
						|
            return f"{event_type_name} {self.event_time} (id={self.id}): {self.modified_user!r}"
 | 
						|
        if self.modified_stream is not None:
 | 
						|
            return f"{event_type_name} {self.event_time} (id={self.id}): {self.modified_stream!r}"
 | 
						|
        if self.modified_user_group is not None:
 | 
						|
            return (
 | 
						|
                f"{event_type_name} {self.event_time} (id={self.id}): {self.modified_user_group!r}"
 | 
						|
            )
 | 
						|
        return f"{event_type_name} {self.event_time} (id={self.id}): {self.realm!r}"
 |