realm: Create RealmAuditLog entry when adding realm linkifiers.

This commit also adds 'acting_user' parameter to do_add_linkifier
function.

Fixes a part of #21268.
This commit is contained in:
Sahil Batra 2022-03-14 16:20:24 +05:30 committed by Tim Abbott
parent ef9c52011d
commit 4f1dd0710c
7 changed files with 67 additions and 5 deletions

View File

@ -1,9 +1,14 @@
from typing import Dict, List, Optional
import orjson
from django.utils.timezone import now as timezone_now
from zerver.lib.types import LinkifierDict
from zerver.models import (
Realm,
RealmAuditLog,
RealmFilter,
UserProfile,
active_user_ids,
linkifiers_for_realm,
realm_filters_for_realm,
@ -27,7 +32,9 @@ def notify_linkifiers(realm: Realm, realm_linkifiers: List[LinkifierDict]) -> No
# RegExp syntax. In addition to JS-compatible syntax, the following features are available:
# * Named groups will be converted to numbered groups automatically
# * Inline-regex flags will be stripped, and where possible translated to RegExp-wide flags
def do_add_linkifier(realm: Realm, pattern: str, url_format_string: str) -> int:
def do_add_linkifier(
realm: Realm, pattern: str, url_format_string: str, *, acting_user: Optional[UserProfile]
) -> int:
pattern = pattern.strip()
url_format_string = url_format_string.strip()
linkifier = RealmFilter(realm=realm, pattern=pattern, url_format_string=url_format_string)
@ -35,6 +42,22 @@ def do_add_linkifier(realm: Realm, pattern: str, url_format_string: str) -> int:
linkifier.save()
realm_linkifiers = linkifiers_for_realm(realm.id)
RealmAuditLog.objects.create(
realm=realm,
acting_user=acting_user,
event_type=RealmAuditLog.REALM_LINKIFIER_ADDED,
event_time=timezone_now(),
extra_data=orjson.dumps(
{
"realm_linkifiers": realm_linkifiers,
"added_linkifier": LinkifierDict(
pattern=pattern,
url_format=url_format_string,
id=linkifier.id,
),
}
).decode(),
)
notify_linkifiers(realm, realm_linkifiers)
return linkifier.id

View File

@ -56,7 +56,7 @@ Example: ./manage.py edit_linkifiers --realm=zulip --op=show
if not url_format_string:
self.print_help("./manage.py", "edit_linkifiers")
raise CommandError
do_add_linkifier(realm, pattern, url_format_string)
do_add_linkifier(realm, pattern, url_format_string, acting_user=None)
sys.exit(0)
elif options["op"] == "remove":
do_remove_linkifier(realm, pattern=pattern)

View File

@ -4253,6 +4253,7 @@ class AbstractRealmAuditLog(models.Model):
REALM_DOMAIN_REMOVED = 220
REALM_PLAYGROUND_ADDED = 221
REALM_PLAYGROUND_REMOVED = 222
REALM_LINKIFIER_ADDED = 223
SUBSCRIPTION_CREATED = 301
SUBSCRIPTION_ACTIVATED = 302

View File

@ -272,7 +272,10 @@ def get_temp_user_group_id() -> Dict[str, object]:
@openapi_param_value_generator(["/realm/filters/{filter_id}:delete"])
def remove_realm_filters() -> Dict[str, object]:
filter_id = do_add_linkifier(
get_realm("zulip"), "#(?P<id>[0-9]{2,8})", "https://github.com/zulip/zulip/pull/%(id)s"
get_realm("zulip"),
"#(?P<id>[0-9]{2,8})",
"https://github.com/zulip/zulip/pull/%(id)s",
acting_user=None,
)
return {
"filter_id": filter_id,

View File

@ -23,6 +23,7 @@ from zerver.actions.realm_domains import (
do_remove_realm_domain,
)
from zerver.actions.realm_icon import do_change_icon_source
from zerver.actions.realm_linkifiers import do_add_linkifier
from zerver.actions.realm_playgrounds import do_add_realm_playground, do_remove_realm_playground
from zerver.actions.realm_settings import (
do_deactivate_realm,
@ -52,7 +53,7 @@ from zerver.lib.message import get_last_message_id
from zerver.lib.stream_traffic import get_streams_traffic
from zerver.lib.streams import create_stream_if_needed
from zerver.lib.test_classes import ZulipTestCase
from zerver.lib.types import RealmPlaygroundDict
from zerver.lib.types import LinkifierDict, RealmPlaygroundDict
from zerver.lib.utils import assert_is_not_none
from zerver.models import (
Message,
@ -67,6 +68,7 @@ from zerver.models import (
get_realm_domains,
get_realm_playgrounds,
get_stream,
linkifiers_for_realm,
)
@ -805,3 +807,34 @@ class TestRealmAuditLog(ZulipTestCase):
).count(),
1,
)
def test_realm_linkifier_entries(self) -> None:
user = self.example_user("iago")
intial_linkifiers = linkifiers_for_realm(user.realm.id)
now = timezone_now()
linkifier_id = do_add_linkifier(
user.realm,
pattern="#(?P<id>[123])",
url_format_string="https://realm.com/my_realm_filter/%(id)s",
acting_user=user,
)
added_linkfier = LinkifierDict(
pattern="#(?P<id>[123])",
url_format="https://realm.com/my_realm_filter/%(id)s",
id=linkifier_id,
)
expected_extra_data = {
"realm_linkifiers": intial_linkifiers + [added_linkfier],
"added_linkifier": added_linkfier,
}
self.assertEqual(
RealmAuditLog.objects.filter(
realm=user.realm,
event_type=RealmAuditLog.REALM_LINKIFIER_ADDED,
event_time__gte=now,
acting_user=user,
extra_data=orjson.dumps(expected_extra_data).decode(),
).count(),
1,
)

View File

@ -1795,7 +1795,8 @@ class NormalActionsTest(BaseAction):
url = "https://realm.com/my_realm_filter/%(id)s"
events = self.verify_action(
lambda: do_add_linkifier(self.user_profile.realm, regex, url), num_events=2
lambda: do_add_linkifier(self.user_profile.realm, regex, url, acting_user=None),
num_events=2,
)
check_realm_linkifiers("events[0]", events[0])
check_realm_filters("events[1]", events[1])

View File

@ -33,6 +33,7 @@ def create_linkifier(
realm=user_profile.realm,
pattern=pattern,
url_format_string=url_format_string,
acting_user=user_profile,
)
return json_success(request, data={"id": linkifier_id})
except ValidationError as e: