Skip to content

Commit 0852a2f

Browse files
authored
Log content and qa changes (#5203)
1 parent d540b98 commit 0852a2f

File tree

4 files changed

+80
-13
lines changed

4 files changed

+80
-13
lines changed

kobo/apps/audit_log/audit_actions.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,21 @@
22

33

44
class AuditAction(models.TextChoices):
5+
ARCHIVE = 'archive'
6+
AUTH = 'auth'
57
CREATE = 'create'
68
DELETE = 'delete'
9+
DEPLOY = 'deploy'
10+
DISABLE_SHARING = 'disable-sharing'
11+
ENABLE_SHARING = 'enable-sharing'
712
IN_TRASH = 'in-trash'
13+
MODIFY_SHARING = 'modify_sharing'
814
PUT_BACK = 'put-back'
15+
REDEPLOY = 'redeploy'
916
REMOVE = 'remove'
10-
UPDATE = 'update'
11-
AUTH = 'auth'
12-
DEPLOY = 'deploy'
13-
ARCHIVE = 'archive'
1417
UNARCHIVE = 'unarchive'
15-
REDEPLOY = 'redeploy'
18+
UPDATE = 'update'
19+
UPDATE_CONTENT = 'update-content'
1620
UPDATE_NAME = 'update-name'
1721
UPDATE_SETTINGS = 'update-settings'
18-
ENABLE_SHARING = 'enable-sharing'
19-
DISABLE_SHARING = 'disable-sharing'
20-
MODIFY_SHARING = 'modify_sharing'
22+
UPDATE_QA = 'update-qa'

kobo/apps/audit_log/models.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -379,17 +379,15 @@ def create_from_detail_request(cls, request):
379379
'log_subtype': PROJECT_HISTORY_LOG_PROJECT_SUBTYPE,
380380
'ip_address': get_client_ip(request),
381381
'source': get_human_readable_client_user_agent(request),
382+
'latest_version_uid': updated_data['latest_version.uid']
382383
}
383384

384-
# always store the latest version uid
385-
common_metadata.update(
386-
{'latest_version_uid': updated_data['latest_version.uid']}
387-
)
388-
389385
changed_field_to_action_map = {
390386
'name': cls.name_change,
391387
'settings': cls.settings_change,
392388
'data_sharing': cls.sharing_change,
389+
'content': cls.content_change,
390+
'advanced_features.qual.qual_survey': cls.qa_change,
393391
}
394392

395393
for field, method in changed_field_to_action_map.items():
@@ -462,3 +460,15 @@ def sharing_change(old_fields, new_fields):
462460
shared_fields_dict[ADDED] = added_fields
463461
shared_fields_dict[REMOVED] = removed_fields
464462
return action, {'shared_fields': shared_fields_dict}
463+
464+
@staticmethod
465+
def content_change(*_):
466+
# content is too long/complicated for meaningful comparison,
467+
# so don't store values
468+
return AuditAction.UPDATE_CONTENT, {}
469+
470+
@staticmethod
471+
def qa_change(_, new_field):
472+
# qa dictionary is complicated to parse and determine
473+
# what actually changed, so just return the new dict
474+
return AuditAction.UPDATE_QA, {'qa': {NEW: new_field}}

kobo/apps/audit_log/tests/test_project_history_logs.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import copy
22

3+
import jsonschema.exceptions
34
from django.test import override_settings
45
from django.urls import reverse
56

@@ -375,3 +376,55 @@ def test_modify_sharing_creates_log(self):
375376
)
376377
self.assertEqual(log_metadata['shared_fields'][ADDED], ['q2'])
377378
self.assertEqual(log_metadata['shared_fields'][REMOVED], ['q1'])
379+
380+
def test_update_content_creates_log(self):
381+
self._base_endpoint_test(
382+
patch=True,
383+
url_name=self.detail_url,
384+
request_data={'content': {'some': 'thing'}},
385+
expected_action=AuditAction.UPDATE_CONTENT,
386+
)
387+
388+
def test_update_qa_creates_log(self):
389+
request_data = {
390+
'advanced_features': {
391+
'qual': {
392+
'qual_survey': [
393+
{
394+
'type': 'qual_note',
395+
'uuid': '12345',
396+
'scope': 'by_question#survey',
397+
'xpath': 'q1',
398+
'labels': {'_default': 'QA Question'},
399+
# requests to remove a question just add this
400+
# option rather than actually deleting anything
401+
'options': {'deleted': True},
402+
}
403+
]
404+
}
405+
}
406+
}
407+
408+
log_metadata = self._base_endpoint_test(
409+
patch=True,
410+
url_name=self.detail_url,
411+
request_data=request_data,
412+
expected_action=AuditAction.UPDATE_QA,
413+
)
414+
415+
self.assertEqual(
416+
log_metadata['qa'][NEW],
417+
request_data['advanced_features']['qual']['qual_survey'],
418+
)
419+
420+
def test_failed_qa_update_does_not_create_log(self):
421+
# badly formatted QA dict should result in an error before update
422+
request_data = {'advanced_features': {'qual': {'qual_survey': ['bad']}}}
423+
with self.assertRaises(jsonschema.exceptions.ValidationError):
424+
self.client.patch(
425+
reverse('api_v2:asset-detail', kwargs={'uid': self.asset.uid}),
426+
data=request_data,
427+
format='json',
428+
)
429+
430+
self.assertEqual(ProjectHistoryLog.objects.count(), 0)

kpi/views/v2/asset.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,8 @@ class AssetViewSet(
387387
'settings',
388388
'latest_version.uid',
389389
'data_sharing',
390+
'content',
391+
'advanced_features.qual.qual_survey',
390392
]
391393
log_type = AuditType.PROJECT_HISTORY
392394

0 commit comments

Comments
 (0)