audit-log: Move user event types to AuditLogEventType enum.

Event types moved: USER_CREATED, USER_ACTIVATED, USER_DEACTIVATED
USER_REACTIVATED, USER_ROLE_CHANGED, USER_DELETED
USER_DELETED_PRESERVING_MESSAGES
This commit is contained in:
Lauryn Menard 2024-08-30 18:15:41 +02:00 committed by Tim Abbott
parent c0100a3c4c
commit e5daa3470f
11 changed files with 106 additions and 91 deletions

View File

@ -20,7 +20,8 @@ from analytics.models import (
installation_epoch, installation_epoch,
) )
from zerver.lib.timestamp import ceiling_to_day, ceiling_to_hour, floor_to_hour, verify_UTC from zerver.lib.timestamp import ceiling_to_day, ceiling_to_hour, floor_to_hour, verify_UTC
from zerver.models import Message, Realm, RealmAuditLog, Stream, UserActivityInterval, UserProfile from zerver.models import Message, Realm, Stream, UserActivityInterval, UserProfile
from zerver.models.realm_audit_logs import AuditLogEventType
if settings.ZILENCER_ENABLED: if settings.ZILENCER_ENABLED:
from zilencer.models import ( from zilencer.models import (
@ -679,7 +680,7 @@ def count_message_by_stream_query(realm: Realm | None) -> QueryFn:
# Hardcodes the query needed for active_users_audit:is_bot:day. # Hardcodes the query needed for active_users_audit:is_bot:day.
# Assumes that a user cannot have two RealmAuditLog entries with the # Assumes that a user cannot have two RealmAuditLog entries with the
# same event_time and event_type in [RealmAuditLog.USER_CREATED, # same event_time and event_type in [AuditLogEventType.USER_CREATED,
# USER_DEACTIVATED, etc]. In particular, it's important to ensure # USER_DEACTIVATED, etc]. In particular, it's important to ensure
# that migrations don't cause that to happen. # that migrations don't cause that to happen.
def check_realmauditlog_by_user_query(realm: Realm | None) -> QueryFn: def check_realmauditlog_by_user_query(realm: Realm | None) -> QueryFn:
@ -713,10 +714,10 @@ def check_realmauditlog_by_user_query(realm: Realm | None) -> QueryFn:
""" """
).format( ).format(
**kwargs, **kwargs,
user_created=Literal(RealmAuditLog.USER_CREATED), user_created=Literal(AuditLogEventType.USER_CREATED),
user_activated=Literal(RealmAuditLog.USER_ACTIVATED), user_activated=Literal(AuditLogEventType.USER_ACTIVATED),
user_deactivated=Literal(RealmAuditLog.USER_DEACTIVATED), user_deactivated=Literal(AuditLogEventType.USER_DEACTIVATED),
user_reactivated=Literal(RealmAuditLog.USER_REACTIVATED), user_reactivated=Literal(AuditLogEventType.USER_REACTIVATED),
realm_clause=realm_clause, realm_clause=realm_clause,
) )
@ -789,10 +790,10 @@ def count_realm_active_humans_query(realm: Realm | None) -> QueryFn:
""" """
).format( ).format(
**kwargs, **kwargs,
user_created=Literal(RealmAuditLog.USER_CREATED), user_created=Literal(AuditLogEventType.USER_CREATED),
user_activated=Literal(RealmAuditLog.USER_ACTIVATED), user_activated=Literal(AuditLogEventType.USER_ACTIVATED),
user_deactivated=Literal(RealmAuditLog.USER_DEACTIVATED), user_deactivated=Literal(AuditLogEventType.USER_DEACTIVATED),
user_reactivated=Literal(RealmAuditLog.USER_REACTIVATED), user_reactivated=Literal(AuditLogEventType.USER_REACTIVATED),
realm_clause=realm_clause, realm_clause=realm_clause,
) )

View File

@ -78,6 +78,7 @@ from zerver.models import (
from zerver.models.clients import get_client from zerver.models.clients import get_client
from zerver.models.groups import SystemGroups from zerver.models.groups import SystemGroups
from zerver.models.messages import Attachment from zerver.models.messages import Attachment
from zerver.models.realm_audit_logs import AuditLogEventType
from zerver.models.scheduled_jobs import NotificationTriggers from zerver.models.scheduled_jobs import NotificationTriggers
from zerver.models.users import get_user, is_cross_realm_bot_email from zerver.models.users import get_user, is_cross_realm_bot_email
from zilencer.models import ( from zilencer.models import (
@ -151,7 +152,7 @@ class AnalyticsTestCase(ZulipTestCase):
realm=kwargs["realm"], realm=kwargs["realm"],
acting_user=None, acting_user=None,
modified_user=user, modified_user=user,
event_type=RealmAuditLog.USER_CREATED, event_type=AuditLogEventType.USER_CREATED,
event_time=kwargs["date_joined"], event_time=kwargs["date_joined"],
extra_data={ extra_data={
RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(kwargs["realm"]) RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(kwargs["realm"])
@ -1842,50 +1843,50 @@ class TestActiveUsersAudit(AnalyticsTestCase):
) )
def test_user_deactivated_in_future(self) -> None: def test_user_deactivated_in_future(self) -> None:
self.add_event(RealmAuditLog.USER_CREATED, 1) self.add_event(AuditLogEventType.USER_CREATED, 1)
self.add_event(RealmAuditLog.USER_DEACTIVATED, 0) self.add_event(AuditLogEventType.USER_DEACTIVATED, 0)
do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO) do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO)
self.assertTableState(RealmCount, ["subgroup"], [["false"]]) self.assertTableState(RealmCount, ["subgroup"], [["false"]])
def test_user_reactivated_in_future(self) -> None: def test_user_reactivated_in_future(self) -> None:
self.add_event(RealmAuditLog.USER_DEACTIVATED, 1) self.add_event(AuditLogEventType.USER_DEACTIVATED, 1)
self.add_event(RealmAuditLog.USER_REACTIVATED, 0) self.add_event(AuditLogEventType.USER_REACTIVATED, 0)
do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO) do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO)
self.assertTableState(RealmCount, [], []) self.assertTableState(RealmCount, [], [])
def test_user_active_then_deactivated_same_day(self) -> None: def test_user_active_then_deactivated_same_day(self) -> None:
self.add_event(RealmAuditLog.USER_CREATED, 1) self.add_event(AuditLogEventType.USER_CREATED, 1)
self.add_event(RealmAuditLog.USER_DEACTIVATED, 0.5) self.add_event(AuditLogEventType.USER_DEACTIVATED, 0.5)
do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO) do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO)
self.assertTableState(RealmCount, [], []) self.assertTableState(RealmCount, [], [])
def test_user_unactive_then_activated_same_day(self) -> None: def test_user_unactive_then_activated_same_day(self) -> None:
self.add_event(RealmAuditLog.USER_DEACTIVATED, 1) self.add_event(AuditLogEventType.USER_DEACTIVATED, 1)
self.add_event(RealmAuditLog.USER_REACTIVATED, 0.5) self.add_event(AuditLogEventType.USER_REACTIVATED, 0.5)
do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO) do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO)
self.assertTableState(RealmCount, ["subgroup"], [["false"]]) self.assertTableState(RealmCount, ["subgroup"], [["false"]])
# Arguably these next two tests are duplicates of the _in_future tests, but are # Arguably these next two tests are duplicates of the _in_future tests, but are
# a guard against future refactorings where they may no longer be duplicates # a guard against future refactorings where they may no longer be duplicates
def test_user_active_then_deactivated_with_day_gap(self) -> None: def test_user_active_then_deactivated_with_day_gap(self) -> None:
self.add_event(RealmAuditLog.USER_CREATED, 2) self.add_event(AuditLogEventType.USER_CREATED, 2)
self.add_event(RealmAuditLog.USER_DEACTIVATED, 1) self.add_event(AuditLogEventType.USER_DEACTIVATED, 1)
process_count_stat(self.stat, self.TIME_ZERO) process_count_stat(self.stat, self.TIME_ZERO)
self.assertTableState( self.assertTableState(
RealmCount, ["subgroup", "end_time"], [["false", self.TIME_ZERO - self.DAY]] RealmCount, ["subgroup", "end_time"], [["false", self.TIME_ZERO - self.DAY]]
) )
def test_user_deactivated_then_reactivated_with_day_gap(self) -> None: def test_user_deactivated_then_reactivated_with_day_gap(self) -> None:
self.add_event(RealmAuditLog.USER_DEACTIVATED, 2) self.add_event(AuditLogEventType.USER_DEACTIVATED, 2)
self.add_event(RealmAuditLog.USER_REACTIVATED, 1) self.add_event(AuditLogEventType.USER_REACTIVATED, 1)
process_count_stat(self.stat, self.TIME_ZERO) process_count_stat(self.stat, self.TIME_ZERO)
self.assertTableState(RealmCount, ["subgroup"], [["false"]]) self.assertTableState(RealmCount, ["subgroup"], [["false"]])
def test_event_types(self) -> None: def test_event_types(self) -> None:
self.add_event(RealmAuditLog.USER_CREATED, 4) self.add_event(AuditLogEventType.USER_CREATED, 4)
self.add_event(RealmAuditLog.USER_DEACTIVATED, 3) self.add_event(AuditLogEventType.USER_DEACTIVATED, 3)
self.add_event(RealmAuditLog.USER_ACTIVATED, 2) self.add_event(AuditLogEventType.USER_ACTIVATED, 2)
self.add_event(RealmAuditLog.USER_REACTIVATED, 1) self.add_event(AuditLogEventType.USER_REACTIVATED, 1)
for i in range(4): for i in range(4):
do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO - i * self.DAY) do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO - i * self.DAY)
self.assertTableState( self.assertTableState(
@ -1903,7 +1904,7 @@ class TestActiveUsersAudit(AnalyticsTestCase):
user3 = self.create_user(skip_auditlog=True, realm=second_realm) user3 = self.create_user(skip_auditlog=True, realm=second_realm)
user4 = self.create_user(skip_auditlog=True, realm=second_realm, is_bot=True) user4 = self.create_user(skip_auditlog=True, realm=second_realm, is_bot=True)
for user in [user1, user2, user3, user4]: for user in [user1, user2, user3, user4]:
self.add_event(RealmAuditLog.USER_CREATED, 1, user=user) self.add_event(AuditLogEventType.USER_CREATED, 1, user=user)
do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO) do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO)
self.assertTableState( self.assertTableState(
RealmCount, RealmCount,
@ -1925,7 +1926,7 @@ class TestActiveUsersAudit(AnalyticsTestCase):
# CountStat.HOUR from CountStat.DAY, this will fail, while many of the # CountStat.HOUR from CountStat.DAY, this will fail, while many of the
# tests above will not. # tests above will not.
def test_update_from_two_days_ago(self) -> None: def test_update_from_two_days_ago(self) -> None:
self.add_event(RealmAuditLog.USER_CREATED, 2) self.add_event(AuditLogEventType.USER_CREATED, 2)
process_count_stat(self.stat, self.TIME_ZERO) process_count_stat(self.stat, self.TIME_ZERO)
self.assertTableState( self.assertTableState(
RealmCount, RealmCount,
@ -1944,14 +1945,14 @@ class TestActiveUsersAudit(AnalyticsTestCase):
self.assertTableState(RealmCount, [], []) self.assertTableState(RealmCount, [], [])
def test_max_audit_entry_is_unrelated(self) -> None: def test_max_audit_entry_is_unrelated(self) -> None:
self.add_event(RealmAuditLog.USER_CREATED, 1) self.add_event(AuditLogEventType.USER_CREATED, 1)
self.add_event(RealmAuditLog.USER_SOFT_ACTIVATED, 0.5) self.add_event(RealmAuditLog.USER_SOFT_ACTIVATED, 0.5)
do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO) do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO)
self.assertTableState(RealmCount, ["subgroup"], [["false"]]) self.assertTableState(RealmCount, ["subgroup"], [["false"]])
# Simultaneous related audit entries should not be allowed, and so not testing for that. # Simultaneous related audit entries should not be allowed, and so not testing for that.
def test_simultaneous_unrelated_audit_entry(self) -> None: def test_simultaneous_unrelated_audit_entry(self) -> None:
self.add_event(RealmAuditLog.USER_CREATED, 1) self.add_event(AuditLogEventType.USER_CREATED, 1)
self.add_event(RealmAuditLog.USER_SOFT_ACTIVATED, 1) self.add_event(RealmAuditLog.USER_SOFT_ACTIVATED, 1)
do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO) do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO)
self.assertTableState(RealmCount, ["subgroup"], [["false"]]) self.assertTableState(RealmCount, ["subgroup"], [["false"]])
@ -1960,10 +1961,10 @@ class TestActiveUsersAudit(AnalyticsTestCase):
user1 = self.create_user(skip_auditlog=True) user1 = self.create_user(skip_auditlog=True)
user2 = self.create_user(skip_auditlog=True) user2 = self.create_user(skip_auditlog=True)
user3 = self.create_user(skip_auditlog=True) user3 = self.create_user(skip_auditlog=True)
self.add_event(RealmAuditLog.USER_CREATED, 0.5, user=user1) self.add_event(AuditLogEventType.USER_CREATED, 0.5, user=user1)
self.add_event(RealmAuditLog.USER_CREATED, 0.5, user=user2) self.add_event(AuditLogEventType.USER_CREATED, 0.5, user=user2)
self.add_event(RealmAuditLog.USER_CREATED, 1, user=user3) self.add_event(AuditLogEventType.USER_CREATED, 1, user=user3)
self.add_event(RealmAuditLog.USER_DEACTIVATED, 0.5, user=user3) self.add_event(AuditLogEventType.USER_DEACTIVATED, 0.5, user=user3)
do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO) do_fill_count_stat_at_hour(self.stat, self.TIME_ZERO)
self.assertTableState(RealmCount, ["value", "subgroup"], [[2, "false"]]) self.assertTableState(RealmCount, ["value", "subgroup"], [[2, "false"]])

View File

@ -9,6 +9,7 @@ from corporate.lib.stripe import add_months
from corporate.models import Customer, CustomerPlan, LicenseLedger from corporate.models import Customer, CustomerPlan, LicenseLedger
from zerver.lib.test_classes import ZulipTestCase from zerver.lib.test_classes import ZulipTestCase
from zerver.models import Client, UserActivity, UserProfile from zerver.models import Client, UserActivity, UserProfile
from zerver.models.realm_audit_logs import AuditLogEventType
from zilencer.models import ( from zilencer.models import (
RemoteRealm, RemoteRealm,
RemoteRealmAuditLog, RemoteRealmAuditLog,
@ -23,7 +24,7 @@ data_list = [
{ {
"server_id": 1, "server_id": 1,
"realm_id": 1, "realm_id": 1,
"event_type": RemoteRealmAuditLog.USER_CREATED, "event_type": AuditLogEventType.USER_CREATED,
"event_time": event_time, "event_time": event_time,
"extra_data": { "extra_data": {
RemoteRealmAuditLog.ROLE_COUNT: { RemoteRealmAuditLog.ROLE_COUNT: {
@ -40,7 +41,7 @@ data_list = [
{ {
"server_id": 1, "server_id": 1,
"realm_id": 1, "realm_id": 1,
"event_type": RemoteRealmAuditLog.USER_ROLE_CHANGED, "event_type": AuditLogEventType.USER_ROLE_CHANGED,
"event_time": event_time, "event_time": event_time,
"extra_data": { "extra_data": {
RemoteRealmAuditLog.ROLE_COUNT: { RemoteRealmAuditLog.ROLE_COUNT: {
@ -57,7 +58,7 @@ data_list = [
{ {
"server_id": 1, "server_id": 1,
"realm_id": 2, "realm_id": 2,
"event_type": RemoteRealmAuditLog.USER_CREATED, "event_type": AuditLogEventType.USER_CREATED,
"event_time": event_time, "event_time": event_time,
"extra_data": { "extra_data": {
RemoteRealmAuditLog.ROLE_COUNT: { RemoteRealmAuditLog.ROLE_COUNT: {
@ -74,14 +75,14 @@ data_list = [
{ {
"server_id": 1, "server_id": 1,
"realm_id": 2, "realm_id": 2,
"event_type": RemoteRealmAuditLog.USER_CREATED, "event_type": AuditLogEventType.USER_CREATED,
"event_time": event_time, "event_time": event_time,
"extra_data": {}, "extra_data": {},
}, },
{ {
"server_id": 1, "server_id": 1,
"realm_id": 3, "realm_id": 3,
"event_type": RemoteRealmAuditLog.USER_CREATED, "event_type": AuditLogEventType.USER_CREATED,
"event_time": event_time, "event_time": event_time,
"extra_data": { "extra_data": {
RemoteRealmAuditLog.ROLE_COUNT: { RemoteRealmAuditLog.ROLE_COUNT: {
@ -98,7 +99,7 @@ data_list = [
{ {
"server_id": 1, "server_id": 1,
"realm_id": 3, "realm_id": 3,
"event_type": RemoteRealmAuditLog.USER_DEACTIVATED, "event_type": AuditLogEventType.USER_DEACTIVATED,
"event_time": event_time + timedelta(seconds=1), "event_time": event_time + timedelta(seconds=1),
"extra_data": { "extra_data": {
RemoteRealmAuditLog.ROLE_COUNT: { RemoteRealmAuditLog.ROLE_COUNT: {
@ -187,7 +188,7 @@ class ActivityTest(ZulipTestCase):
RemoteRealmAuditLog.objects.create( RemoteRealmAuditLog.objects.create(
server=server, server=server,
realm_id=10, realm_id=10,
event_type=RemoteRealmAuditLog.USER_CREATED, event_type=AuditLogEventType.USER_CREATED,
event_time=timezone_now() - timedelta(days=1), event_time=timezone_now() - timedelta(days=1),
extra_data=extra_data, extra_data=extra_data,
) )
@ -283,7 +284,7 @@ class ActivityTest(ZulipTestCase):
RemoteRealmAuditLog.objects.create( RemoteRealmAuditLog.objects.create(
server=server, server=server,
remote_realm=remote_realm, remote_realm=remote_realm,
event_type=RemoteRealmAuditLog.USER_CREATED, event_type=AuditLogEventType.USER_CREATED,
event_time=timezone_now() - timedelta(days=1), event_time=timezone_now() - timedelta(days=1),
extra_data=extra_data, extra_data=extra_data,
) )
@ -291,7 +292,7 @@ class ActivityTest(ZulipTestCase):
RemoteRealmAuditLog.objects.create( RemoteRealmAuditLog.objects.create(
server=server, server=server,
realm_id=realm_id, realm_id=realm_id,
event_type=RemoteRealmAuditLog.USER_CREATED, event_type=AuditLogEventType.USER_CREATED,
event_time=timezone_now() - timedelta(days=1), event_time=timezone_now() - timedelta(days=1),
extra_data=extra_data, extra_data=extra_data,
) )

View File

@ -93,6 +93,7 @@ from zerver.lib.test_helpers import activate_push_notification_service
from zerver.lib.timestamp import datetime_to_timestamp, timestamp_to_datetime from zerver.lib.timestamp import datetime_to_timestamp, timestamp_to_datetime
from zerver.lib.utils import assert_is_not_none from zerver.lib.utils import assert_is_not_none
from zerver.models import Message, Realm, RealmAuditLog, Recipient, UserProfile from zerver.models import Message, Realm, RealmAuditLog, Recipient, UserProfile
from zerver.models.realm_audit_logs import AuditLogEventType
from zerver.models.realms import get_realm from zerver.models.realms import get_realm
from zerver.models.users import get_system_bot from zerver.models.users import get_system_bot
from zilencer.lib.remote_counts import MissingDataError from zilencer.lib.remote_counts import MissingDataError
@ -6058,7 +6059,7 @@ class TestRemoteRealmBillingSession(StripeTestCase):
{ {
"server": remote_server, "server": remote_server,
"remote_realm": remote_realm, "remote_realm": remote_realm,
"event_type": RemoteRealmAuditLog.USER_CREATED, "event_type": AuditLogEventType.USER_CREATED,
"event_time": event_time, "event_time": event_time,
"extra_data": { "extra_data": {
RemoteRealmAuditLog.ROLE_COUNT: { RemoteRealmAuditLog.ROLE_COUNT: {
@ -6075,7 +6076,7 @@ class TestRemoteRealmBillingSession(StripeTestCase):
{ {
"server": remote_server, "server": remote_server,
"remote_realm": remote_realm, "remote_realm": remote_realm,
"event_type": RemoteRealmAuditLog.USER_ROLE_CHANGED, "event_type": AuditLogEventType.USER_ROLE_CHANGED,
"event_time": event_time, "event_time": event_time,
"extra_data": { "extra_data": {
RemoteRealmAuditLog.ROLE_COUNT: { RemoteRealmAuditLog.ROLE_COUNT: {

View File

@ -58,6 +58,7 @@ from zerver.models import (
UserProfile, UserProfile,
) )
from zerver.models.groups import SystemGroups from zerver.models.groups import SystemGroups
from zerver.models.realm_audit_logs import AuditLogEventType
from zerver.models.users import active_user_ids, bot_owner_user_ids, get_system_bot from zerver.models.users import active_user_ids, bot_owner_user_ids, get_system_bot
from zerver.tornado.django_api import send_event_on_commit from zerver.tornado.django_api import send_event_on_commit
@ -539,7 +540,7 @@ def do_create_user(
realm=user_profile.realm, realm=user_profile.realm,
acting_user=acting_user, acting_user=acting_user,
modified_user=user_profile, modified_user=user_profile,
event_type=RealmAuditLog.USER_CREATED, event_type=AuditLogEventType.USER_CREATED,
event_time=event_time, event_time=event_time,
extra_data={ extra_data={
RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user_profile.realm), RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user_profile.realm),
@ -655,7 +656,7 @@ def do_activate_mirror_dummy_user(
realm=user_profile.realm, realm=user_profile.realm,
modified_user=user_profile, modified_user=user_profile,
acting_user=acting_user, acting_user=acting_user,
event_type=RealmAuditLog.USER_ACTIVATED, event_type=AuditLogEventType.USER_ACTIVATED,
event_time=event_time, event_time=event_time,
extra_data={ extra_data={
RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user_profile.realm), RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user_profile.realm),
@ -683,7 +684,7 @@ def do_reactivate_user(user_profile: UserProfile, *, acting_user: UserProfile |
realm=user_profile.realm, realm=user_profile.realm,
modified_user=user_profile, modified_user=user_profile,
acting_user=acting_user, acting_user=acting_user,
event_type=RealmAuditLog.USER_REACTIVATED, event_type=AuditLogEventType.USER_REACTIVATED,
event_time=event_time, event_time=event_time,
extra_data={ extra_data={
RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user_profile.realm), RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user_profile.realm),

View File

@ -42,6 +42,7 @@ from zerver.models import (
UserProfile, UserProfile,
) )
from zerver.models.bots import get_bot_services from zerver.models.bots import get_bot_services
from zerver.models.realm_audit_logs import AuditLogEventType
from zerver.models.realms import get_fake_email_domain from zerver.models.realms import get_fake_email_domain
from zerver.models.users import ( from zerver.models.users import (
active_non_guest_user_ids, active_non_guest_user_ids,
@ -105,7 +106,7 @@ def do_delete_user(user_profile: UserProfile, *, acting_user: UserProfile | None
realm=replacement_user.realm, realm=replacement_user.realm,
modified_user=replacement_user, modified_user=replacement_user,
acting_user=acting_user, acting_user=acting_user,
event_type=RealmAuditLog.USER_DELETED, event_type=AuditLogEventType.USER_DELETED,
event_time=timezone_now(), event_time=timezone_now(),
) )
@ -236,7 +237,7 @@ def do_delete_user_preserving_messages(user_profile: UserProfile) -> None:
realm=replacement_user.realm, realm=replacement_user.realm,
modified_user=replacement_user, modified_user=replacement_user,
acting_user=None, acting_user=None,
event_type=RealmAuditLog.USER_DELETED_PRESERVING_MESSAGES, event_type=AuditLogEventType.USER_DELETED_PRESERVING_MESSAGES,
event_time=timezone_now(), event_time=timezone_now(),
) )
@ -352,7 +353,7 @@ def do_deactivate_user(
realm=user_profile.realm, realm=user_profile.realm,
modified_user=user_profile, modified_user=user_profile,
acting_user=acting_user, acting_user=acting_user,
event_type=RealmAuditLog.USER_DEACTIVATED, event_type=AuditLogEventType.USER_DEACTIVATED,
event_time=event_time, event_time=event_time,
extra_data={ extra_data={
RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user_profile.realm), RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user_profile.realm),
@ -463,7 +464,7 @@ def do_change_user_role(
realm=user_profile.realm, realm=user_profile.realm,
modified_user=user_profile, modified_user=user_profile,
acting_user=acting_user, acting_user=acting_user,
event_type=RealmAuditLog.USER_ROLE_CHANGED, event_type=AuditLogEventType.USER_ROLE_CHANGED,
event_time=timezone_now(), event_time=timezone_now(),
extra_data={ extra_data={
RealmAuditLog.OLD_VALUE: old_value, RealmAuditLog.OLD_VALUE: old_value,

View File

@ -19,6 +19,7 @@ from zerver.models import (
UserProfile, UserProfile,
) )
from zerver.models.groups import SystemGroups from zerver.models.groups import SystemGroups
from zerver.models.realm_audit_logs import AuditLogEventType
def bulk_create_users( def bulk_create_users(
@ -96,7 +97,7 @@ def bulk_create_users(
RealmAuditLog( RealmAuditLog(
realm=realm, realm=realm,
modified_user=profile_, modified_user=profile_,
event_type=RealmAuditLog.USER_CREATED, event_type=AuditLogEventType.USER_CREATED,
event_time=profile_.date_joined, event_time=profile_.date_joined,
) )
for profile_ in profiles_to_create for profile_ in profiles_to_create

View File

@ -1,3 +1,5 @@
from enum import IntEnum, unique
from django.core.serializers.json import DjangoJSONEncoder from django.core.serializers.json import DjangoJSONEncoder
from django.db import models from django.db import models
from django.db.models import CASCADE, Q from django.db.models import CASCADE, Q
@ -9,6 +11,17 @@ from zerver.models.streams import Stream
from zerver.models.users import UserProfile 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
class AbstractRealmAuditLog(models.Model): class AbstractRealmAuditLog(models.Model):
"""Defines fields common to RealmAuditLog and RemoteRealmAuditLog.""" """Defines fields common to RealmAuditLog and RemoteRealmAuditLog."""
@ -28,14 +41,6 @@ class AbstractRealmAuditLog(models.Model):
extra_data = models.JSONField(default=dict, encoder=DjangoJSONEncoder) extra_data = models.JSONField(default=dict, encoder=DjangoJSONEncoder)
# Event types # Event types
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_SOFT_ACTIVATED = 120 USER_SOFT_ACTIVATED = 120
USER_SOFT_DEACTIVATED = 121 USER_SOFT_DEACTIVATED = 121
USER_PASSWORD_CHANGED = 122 USER_PASSWORD_CHANGED = 122
@ -149,11 +154,11 @@ class AbstractRealmAuditLog(models.Model):
# billing for mobile push notifications is enabled. Every billing # billing for mobile push notifications is enabled. Every billing
# event_type should have ROLE_COUNT populated in extra_data. # event_type should have ROLE_COUNT populated in extra_data.
SYNCED_BILLING_EVENTS = [ SYNCED_BILLING_EVENTS = [
USER_CREATED, AuditLogEventType.USER_CREATED,
USER_ACTIVATED, AuditLogEventType.USER_ACTIVATED,
USER_DEACTIVATED, AuditLogEventType.USER_DEACTIVATED,
USER_REACTIVATED, AuditLogEventType.USER_REACTIVATED,
USER_ROLE_CHANGED, AuditLogEventType.USER_ROLE_CHANGED,
REALM_DEACTIVATED, REALM_DEACTIVATED,
REALM_REACTIVATED, REALM_REACTIVATED,
REALM_IMPORTED, REALM_IMPORTED,
@ -246,10 +251,10 @@ class RealmAuditLog(AbstractRealmAuditLog):
fields=["modified_user", "event_time"], fields=["modified_user", "event_time"],
condition=Q( condition=Q(
event_type__in=[ event_type__in=[
AbstractRealmAuditLog.USER_CREATED, AuditLogEventType.USER_CREATED,
AbstractRealmAuditLog.USER_ACTIVATED, AuditLogEventType.USER_ACTIVATED,
AbstractRealmAuditLog.USER_DEACTIVATED, AuditLogEventType.USER_DEACTIVATED,
AbstractRealmAuditLog.USER_REACTIVATED, AuditLogEventType.USER_REACTIVATED,
] ]
), ),
), ),

View File

@ -85,6 +85,7 @@ from zerver.models import (
) )
from zerver.models.groups import SystemGroups from zerver.models.groups import SystemGroups
from zerver.models.linkifiers import linkifiers_for_realm from zerver.models.linkifiers import linkifiers_for_realm
from zerver.models.realm_audit_logs import AuditLogEventType
from zerver.models.realm_emoji import EmojiInfo, get_all_custom_emoji_for_realm from zerver.models.realm_emoji import EmojiInfo, get_all_custom_emoji_for_realm
from zerver.models.realm_playgrounds import get_realm_playgrounds from zerver.models.realm_playgrounds import get_realm_playgrounds
from zerver.models.realms import EditTopicPolicyEnum, RealmDomainDict, get_realm, get_realm_domains from zerver.models.realms import EditTopicPolicyEnum, RealmDomainDict, get_realm, get_realm_domains
@ -128,13 +129,13 @@ class TestRealmAuditLog(ZulipTestCase):
self.assertEqual( self.assertEqual(
event_types, event_types,
[ [
RealmAuditLog.USER_CREATED, AuditLogEventType.USER_CREATED,
RealmAuditLog.USER_GROUP_DIRECT_USER_MEMBERSHIP_ADDED, RealmAuditLog.USER_GROUP_DIRECT_USER_MEMBERSHIP_ADDED,
RealmAuditLog.USER_GROUP_DIRECT_USER_MEMBERSHIP_ADDED, RealmAuditLog.USER_GROUP_DIRECT_USER_MEMBERSHIP_ADDED,
RealmAuditLog.USER_DEACTIVATED, AuditLogEventType.USER_DEACTIVATED,
RealmAuditLog.USER_ACTIVATED, AuditLogEventType.USER_ACTIVATED,
RealmAuditLog.USER_DEACTIVATED, AuditLogEventType.USER_DEACTIVATED,
RealmAuditLog.USER_REACTIVATED, AuditLogEventType.USER_REACTIVATED,
], ],
) )
modified_user_group_names = [] modified_user_group_names = []
@ -180,7 +181,7 @@ class TestRealmAuditLog(ZulipTestCase):
old_values_seen = set() old_values_seen = set()
new_values_seen = set() new_values_seen = set()
for event in RealmAuditLog.objects.filter( for event in RealmAuditLog.objects.filter(
event_type=RealmAuditLog.USER_ROLE_CHANGED, event_type=AuditLogEventType.USER_ROLE_CHANGED,
realm=realm, realm=realm,
modified_user=user_profile, modified_user=user_profile,
acting_user=acting_user, acting_user=acting_user,

View File

@ -92,6 +92,7 @@ from zerver.models import (
from zerver.models.clients import get_client from zerver.models.clients import get_client
from zerver.models.groups import SystemGroups from zerver.models.groups import SystemGroups
from zerver.models.presence import PresenceSequence from zerver.models.presence import PresenceSequence
from zerver.models.realm_audit_logs import AuditLogEventType
from zerver.models.realms import get_realm from zerver.models.realms import get_realm
from zerver.models.recipients import get_direct_message_group_hash from zerver.models.recipients import get_direct_message_group_hash
from zerver.models.streams import get_active_streams, get_stream from zerver.models.streams import get_active_streams, get_stream
@ -834,12 +835,12 @@ class RealmImportExportTest(ExportFile):
# by the export, so we'll test that it is handled by getting set to None. # by the export, so we'll test that it is handled by getting set to None.
self.assertTrue( self.assertTrue(
RealmAuditLog.objects.filter( RealmAuditLog.objects.filter(
modified_user=hamlet, event_type=RealmAuditLog.USER_CREATED modified_user=hamlet, event_type=AuditLogEventType.USER_CREATED
).count(), ).count(),
1, 1,
) )
RealmAuditLog.objects.filter( RealmAuditLog.objects.filter(
modified_user=hamlet, event_type=RealmAuditLog.USER_CREATED modified_user=hamlet, event_type=AuditLogEventType.USER_CREATED
).update(acting_user_id=cross_realm_bot.id) ).update(acting_user_id=cross_realm_bot.id)
# data to test import of direct message groups # data to test import of direct message groups
@ -1142,7 +1143,7 @@ class RealmImportExportTest(ExportFile):
imported_hamlet = get_user_by_delivery_email(hamlet.delivery_email, imported_realm) imported_hamlet = get_user_by_delivery_email(hamlet.delivery_email, imported_realm)
realmauditlog = RealmAuditLog.objects.get( realmauditlog = RealmAuditLog.objects.get(
modified_user=imported_hamlet, event_type=RealmAuditLog.USER_CREATED modified_user=imported_hamlet, event_type=AuditLogEventType.USER_CREATED
) )
self.assertEqual(realmauditlog.realm, imported_realm) self.assertEqual(realmauditlog.realm, imported_realm)
# As explained above when setting up the RealmAuditLog row, the .acting_user should have been # As explained above when setting up the RealmAuditLog row, the .acting_user should have been

View File

@ -103,6 +103,7 @@ from zerver.models import (
UserTopic, UserTopic,
) )
from zerver.models.clients import get_client from zerver.models.clients import get_client
from zerver.models.realm_audit_logs import AuditLogEventType
from zerver.models.realms import get_realm from zerver.models.realms import get_realm
from zerver.models.scheduled_jobs import NotificationTriggers from zerver.models.scheduled_jobs import NotificationTriggers
from zerver.models.streams import get_stream from zerver.models.streams import get_stream
@ -877,7 +878,7 @@ class PushBouncerNotificationTest(BouncerTestCase):
} }
RemoteRealmAuditLog.objects.create( RemoteRealmAuditLog.objects.create(
server=remote_server, server=remote_server,
event_type=RealmAuditLog.USER_CREATED, event_type=AuditLogEventType.USER_CREATED,
event_time=current_time - timedelta(minutes=10), event_time=current_time - timedelta(minutes=10),
extra_data={RealmAuditLog.ROLE_COUNT: {RealmAuditLog.ROLE_COUNT_HUMANS: human_counts}}, extra_data={RealmAuditLog.ROLE_COUNT: {RealmAuditLog.ROLE_COUNT_HUMANS: human_counts}},
) )
@ -939,7 +940,7 @@ class PushBouncerNotificationTest(BouncerTestCase):
RemoteRealmAuditLog.objects.create( RemoteRealmAuditLog.objects.create(
server=remote_server, server=remote_server,
event_type=RealmAuditLog.USER_DEACTIVATED, event_type=AuditLogEventType.USER_DEACTIVATED,
event_time=current_time - timedelta(minutes=8), event_time=current_time - timedelta(minutes=8),
extra_data={RealmAuditLog.ROLE_COUNT: {RealmAuditLog.ROLE_COUNT_HUMANS: human_counts}}, extra_data={RealmAuditLog.ROLE_COUNT: {RealmAuditLog.ROLE_COUNT_HUMANS: human_counts}},
) )
@ -1604,7 +1605,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
RealmAuditLog.objects.create( RealmAuditLog.objects.create(
realm=user.realm, realm=user.realm,
modified_user=user, modified_user=user,
event_type=RealmAuditLog.USER_CREATED, event_type=AuditLogEventType.USER_CREATED,
event_time=end_time, event_time=end_time,
extra_data=orjson.dumps( extra_data=orjson.dumps(
{ {
@ -1835,7 +1836,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
RealmAuditLog.objects.create( RealmAuditLog.objects.create(
realm=user.realm, realm=user.realm,
modified_user=user, modified_user=user,
event_type=RealmAuditLog.USER_REACTIVATED, event_type=AuditLogEventType.USER_REACTIVATED,
event_time=end_time, event_time=end_time,
extra_data={ extra_data={
RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user.realm), RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user.realm),
@ -1964,7 +1965,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
realm_audit_log = RealmAuditLog.objects.create( realm_audit_log = RealmAuditLog.objects.create(
realm=user.realm, realm=user.realm,
modified_user=user, modified_user=user,
event_type=RealmAuditLog.USER_CREATED, event_type=AuditLogEventType.USER_CREATED,
event_time=end_time, event_time=end_time,
extra_data=orjson.dumps( extra_data=orjson.dumps(
{ {
@ -2067,7 +2068,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
RealmAuditLog.objects.create( RealmAuditLog.objects.create(
realm=user.realm, realm=user.realm,
modified_user=user, modified_user=user,
event_type=RealmAuditLog.USER_CREATED, event_type=AuditLogEventType.USER_CREATED,
event_time=end_time, event_time=end_time,
extra_data={ extra_data={
RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user.realm), RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user.realm),
@ -2183,7 +2184,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
RealmAuditLog.objects.create( RealmAuditLog.objects.create(
realm=user.realm, realm=user.realm,
modified_user=user, modified_user=user,
event_type=RealmAuditLog.USER_REACTIVATED, event_type=AuditLogEventType.USER_REACTIVATED,
event_time=self.TIME_ZERO, event_time=self.TIME_ZERO,
extra_data={ extra_data={
RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user.realm), RealmAuditLog.ROLE_COUNT: realm_user_count_by_role(user.realm),
@ -2208,7 +2209,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
first_call = False first_call = False
else: else:
# Test that we're respecting SYNCED_BILLING_EVENTS # Test that we're respecting SYNCED_BILLING_EVENTS
self.assertIn(f'"event_type":{RealmAuditLog.USER_REACTIVATED}', str(args)) self.assertIn(f'"event_type":{AuditLogEventType.USER_REACTIVATED}', str(args))
self.assertNotIn(f'"event_type":{RealmAuditLog.REALM_LOGO_CHANGED}', str(args)) self.assertNotIn(f'"event_type":{RealmAuditLog.REALM_LOGO_CHANGED}', str(args))
# Test that we're respecting REALMAUDITLOG_PUSHED_FIELDS # Test that we're respecting REALMAUDITLOG_PUSHED_FIELDS
self.assertIn("backfilled", str(args)) self.assertIn("backfilled", str(args))
@ -2230,7 +2231,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
realm=user.realm, realm=user.realm,
modified_user=user, modified_user=user,
backfilled=True, backfilled=True,
event_type=RealmAuditLog.USER_REACTIVATED, event_type=AuditLogEventType.USER_REACTIVATED,
event_time=self.TIME_ZERO, event_time=self.TIME_ZERO,
extra_data=orjson.dumps({RealmAuditLog.ROLE_COUNT: user_count}).decode(), extra_data=orjson.dumps({RealmAuditLog.ROLE_COUNT: user_count}).decode(),
) )
@ -2243,7 +2244,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
self.assertEqual(remote_log_entry.backfilled, True) self.assertEqual(remote_log_entry.backfilled, True)
assert remote_log_entry.extra_data is not None assert remote_log_entry.extra_data is not None
self.assertEqual(remote_log_entry.extra_data, {RealmAuditLog.ROLE_COUNT: user_count}) self.assertEqual(remote_log_entry.extra_data, {RealmAuditLog.ROLE_COUNT: user_count})
self.assertEqual(remote_log_entry.event_type, RealmAuditLog.USER_REACTIVATED) self.assertEqual(remote_log_entry.event_type, AuditLogEventType.USER_REACTIVATED)
# This verifies that the bouncer is backwards-compatible with remote servers using # This verifies that the bouncer is backwards-compatible with remote servers using
# TextField to store extra_data. # TextField to store extra_data.
@ -2262,7 +2263,7 @@ class AnalyticsBouncerTest(BouncerTestCase):
log_entry = RealmAuditLog.objects.create( log_entry = RealmAuditLog.objects.create(
realm=user.realm, realm=user.realm,
modified_user=user, modified_user=user,
event_type=RealmAuditLog.USER_REACTIVATED, event_type=AuditLogEventType.USER_REACTIVATED,
event_time=self.TIME_ZERO, event_time=self.TIME_ZERO,
extra_data=orjson.dumps( extra_data=orjson.dumps(
{ {