diff --git a/zilencer/management/commands/add_remote_server.py b/zilencer/management/commands/add_remote_server.py index 698ab65471..2bdab3c3d1 100644 --- a/zilencer/management/commands/add_remote_server.py +++ b/zilencer/management/commands/add_remote_server.py @@ -1,8 +1,10 @@ from argparse import ArgumentParser from typing import Any +from django.db import transaction + from zerver.lib.management import ZulipBaseCommand -from zilencer.models import RemoteZulipServer +from zilencer.models import RemoteZulipServer, RemoteZulipServerAuditLog class Command(ZulipBaseCommand): @@ -18,9 +20,15 @@ class Command(ZulipBaseCommand): group.add_argument("--email", "-e", required=True, help="a contact email address") def handle(self, *args: Any, **options: Any) -> None: - RemoteZulipServer.objects.create( - uuid=options["uuid"], - api_key=options["key"], - hostname=options["hostname"], - contact_email=options["email"], - ) + with transaction.atomic(): + remote_server = RemoteZulipServer.objects.create( + uuid=options["uuid"], + api_key=options["key"], + hostname=options["hostname"], + contact_email=options["email"], + ) + RemoteZulipServerAuditLog.objects.create( + event_type=RemoteZulipServerAuditLog.REMOTE_SERVER_CREATED, + server=remote_server, + event_time=remote_server.last_updated, + ) diff --git a/zilencer/migrations/0022_remotezulipserver_create_audit_log_backfill.py b/zilencer/migrations/0022_remotezulipserver_create_audit_log_backfill.py new file mode 100644 index 0000000000..f6ec6bddd0 --- /dev/null +++ b/zilencer/migrations/0022_remotezulipserver_create_audit_log_backfill.py @@ -0,0 +1,45 @@ +from django.db import migrations +from django.db.backends.postgresql.schema import DatabaseSchemaEditor +from django.db.migrations.state import StateApps + + +def backfill_remote_zulip_server_creation_log_events( + apps: StateApps, schema_editor: DatabaseSchemaEditor +) -> None: + RemoteZulipServer = apps.get_model("zilencer", "RemoteZulipServer") + RemoteZulipServerAuditLog = apps.get_model("zilencer", "RemoteZulipServerAuditLog") + RemoteZulipServerAuditLog.REMOTE_SERVER_CREATED = 10215 + + objects_to_create = [] + for remote_server in RemoteZulipServer.objects.all(): + entry = RemoteZulipServerAuditLog( + server=remote_server, + event_type=RemoteZulipServerAuditLog.REMOTE_SERVER_CREATED, + event_time=remote_server.last_updated, + backfilled=True, + ) + objects_to_create.append(entry) + RemoteZulipServerAuditLog.objects.bulk_create(objects_to_create) + + +def reverse_code(apps: StateApps, schema_editor: DatabaseSchemaEditor) -> None: + RemoteZulipServerAuditLog = apps.get_model("zilencer", "RemoteZulipServerAuditLog") + RemoteZulipServerAuditLog.REMOTE_SERVER_CREATED = 10215 + RemoteZulipServerAuditLog.objects.filter( + event_type=RemoteZulipServerAuditLog.REMOTE_SERVER_CREATED, backfilled=True + ).delete() + + +class Migration(migrations.Migration): + + dependencies = [ + ("zilencer", "0021_alter_remotezulipserver_uuid"), + ] + + operations = [ + migrations.RunPython( + backfill_remote_zulip_server_creation_log_events, + reverse_code=reverse_code, + elidable=True, + ) + ] diff --git a/zilencer/views.py b/zilencer/views.py index de8f1f081c..50a5808d45 100644 --- a/zilencer/views.py +++ b/zilencer/views.py @@ -40,6 +40,7 @@ from zilencer.models import ( RemoteRealmAuditLog, RemoteRealmCount, RemoteZulipServer, + RemoteZulipServerAuditLog, ) logger = logging.getLogger(__name__) @@ -108,20 +109,30 @@ def register_remote_server( except ValidationError as e: raise JsonableError(e.message) - remote_server, created = RemoteZulipServer.objects.get_or_create( - uuid=zulip_org_id, - defaults={"hostname": hostname, "contact_email": contact_email, "api_key": zulip_org_key}, - ) - - if not created: - if remote_server.api_key != zulip_org_key: - raise InvalidZulipServerKeyError(zulip_org_id) + with transaction.atomic(): + remote_server, created = RemoteZulipServer.objects.get_or_create( + uuid=zulip_org_id, + defaults={ + "hostname": hostname, + "contact_email": contact_email, + "api_key": zulip_org_key, + }, + ) + if created: + RemoteZulipServerAuditLog.objects.create( + event_type=RemoteZulipServerAuditLog.REMOTE_SERVER_CREATED, + server=remote_server, + event_time=remote_server.last_updated, + ) else: - remote_server.hostname = hostname - remote_server.contact_email = contact_email - if new_org_key is not None: - remote_server.api_key = new_org_key - remote_server.save() + if remote_server.api_key != zulip_org_key: + raise InvalidZulipServerKeyError(zulip_org_id) + else: + remote_server.hostname = hostname + remote_server.contact_email = contact_email + if new_org_key is not None: + remote_server.api_key = new_org_key + remote_server.save() return json_success({"created": created})