audit_log: Log RealmAuditLog in do_set_realm_property.

Log RealmAuditLog in do_set_realm_property and do_remove_realm_domain.
Tests for the changes are written in test_events because it will save
duplicate code for test_change_realm_property.
This commit is contained in:
arpit551
2020-06-29 19:04:19 +05:30
committed by Tim Abbott
parent 6af337c07e
commit ba92666dbd
7 changed files with 38 additions and 14 deletions

View File

@@ -293,9 +293,10 @@ active users in a realm.
# zerver/lib/actions.py
def do_set_realm_property(realm: Realm, name: str, value: bool) -> None:
"""Takes in a realm object, the name of an attribute to update, and the
value to update.
def do_set_realm_property(realm: Realm, name: str, value: bool,
acting_user: Optional[UserProfile]=None) -> None:
"""Takes in a realm object, the name of an attribute to update, the
value to update and and the user who initiated the update.
"""
property_type = Realm.property_types[name]
assert isinstance(value, property_type), (

View File

@@ -266,7 +266,7 @@ def update_realm(
):
realm = user_profile.realm
# ...
do_set_realm_property(realm, k, v)
do_set_realm_property(realm, k, v, acting_user=user_profile)
# ...
```

View File

@@ -667,9 +667,10 @@ def active_humans_in_realm(realm: Realm) -> Sequence[UserProfile]:
return UserProfile.objects.filter(realm=realm, is_active=True, is_bot=False)
def do_set_realm_property(realm: Realm, name: str, value: Any) -> None:
"""Takes in a realm object, the name of an attribute to update, and the
value to update.
def do_set_realm_property(realm: Realm, name: str, value: Any,
acting_user: Optional[UserProfile] = None) -> None:
"""Takes in a realm object, the name of an attribute to update, the
value to update and and the user who initiated the update.
"""
property_type = Realm.property_types[name]
assert isinstance(value, property_type), (
@@ -687,6 +688,14 @@ def do_set_realm_property(realm: Realm, name: str, value: Any) -> None:
)
send_event(realm, event, active_user_ids(realm.id))
event_time = timezone_now()
RealmAuditLog.objects.create(
realm=realm, event_type=RealmAuditLog.REALM_PROPERTY_CHANGED, event_time=event_time,
acting_user=acting_user, extra_data=ujson.dumps({
RealmAuditLog.OLD_VALUE: {'property': name, 'value': old_value},
RealmAuditLog.NEW_VALUE: {'property': name, 'value': value}
}))
if name == "email_address_visibility":
if Realm.EMAIL_ADDRESS_VISIBILITY_EVERYONE not in [old_value, value]:
# We use real email addresses on UserProfile.email only if
@@ -5461,7 +5470,7 @@ def do_change_realm_domain(realm_domain: RealmDomain, allow_subdomains: bool) ->
allow_subdomains=realm_domain.allow_subdomains))
send_event(realm_domain.realm, event, active_user_ids(realm_domain.realm_id))
def do_remove_realm_domain(realm_domain: RealmDomain) -> None:
def do_remove_realm_domain(realm_domain: RealmDomain, acting_user: Optional[UserProfile]=None) -> None:
realm = realm_domain.realm
domain = realm_domain.domain
realm_domain.delete()
@@ -5470,7 +5479,7 @@ def do_remove_realm_domain(realm_domain: RealmDomain) -> None:
# longer restricted to domain, because the feature doesn't do
# anything if there are no domains, and this is probably less
# confusing than the alternative.
do_set_realm_property(realm, 'emails_restricted_to_domains', False)
do_set_realm_property(realm, 'emails_restricted_to_domains', False, acting_user=acting_user)
event = dict(type="realm_domains", op="remove", domain=domain)
send_event(realm, event, active_user_ids(realm.id))

View File

@@ -2729,6 +2729,7 @@ class AbstractRealmAuditLog(models.Model):
REALM_PLAN_TYPE_CHANGED = 204
REALM_LOGO_CHANGED = 205
REALM_EXPORTED = 206
REALM_PROPERTY_CHANGED = 207
SUBSCRIPTION_CREATED = 301
SUBSCRIPTION_ACTIVATED = 302

View File

@@ -2542,12 +2542,25 @@ class RealmPropertyActionTest(BaseAction):
if vals is None:
raise AssertionError(f'No test created for {name}')
do_set_realm_property(self.user_profile.realm, name, vals[0])
for val in vals[1:]:
now = timezone_now()
do_set_realm_property(self.user_profile.realm, name, vals[0], acting_user=self.user_profile)
self.assertEqual(RealmAuditLog.objects.filter(realm=self.user_profile.realm, event_type=RealmAuditLog.REALM_PROPERTY_CHANGED,
event_time__gte=now, acting_user=self.user_profile).count(), 1)
for count, val in enumerate(vals[1:]):
now = timezone_now()
state_change_expected = True
events = self.verify_action(
lambda: do_set_realm_property(self.user_profile.realm, name, val),
lambda: do_set_realm_property(self.user_profile.realm, name, val, acting_user=self.user_profile),
state_change_expected=state_change_expected)
old_value = vals[count]
self.assertEqual(RealmAuditLog.objects.filter(
realm=self.user_profile.realm, event_type=RealmAuditLog.REALM_PROPERTY_CHANGED,
event_time__gte=now, acting_user=self.user_profile,
extra_data=ujson.dumps({
RealmAuditLog.OLD_VALUE: {'property': name, 'value': old_value},
RealmAuditLog.NEW_VALUE: {'property': name, 'value': val}
})).count(), 1)
schema_checker('events[0]', events[0])
def test_change_realm_property(self) -> None:

View File

@@ -126,7 +126,7 @@ def update_realm(
for k, v in list(req_vars.items()):
if v is not None and getattr(realm, k) != v:
do_set_realm_property(realm, k, v)
do_set_realm_property(realm, k, v, acting_user=user_profile)
if isinstance(v, str):
data[k] = 'updated'
else:

View File

@@ -48,7 +48,7 @@ def delete_realm_domain(request: HttpRequest, user_profile: UserProfile,
domain: str) -> HttpResponse:
try:
realm_domain = RealmDomain.objects.get(realm=user_profile.realm, domain=domain)
do_remove_realm_domain(realm_domain)
do_remove_realm_domain(realm_domain, acting_user=user_profile)
except RealmDomain.DoesNotExist:
return json_error(_('No entry found for domain {domain}.').format(domain=domain))
return json_success()