Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create project history logs for the /asset endpoint #5184

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
5 changes: 3 additions & 2 deletions kobo/apps/accounts/tests/test_backend.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import json
from unittest.mock import patch

import responses
from allauth.socialaccount.models import SocialAccount, SocialApp
from django.conf import settings
from django.test import TestCase
from django.test.utils import override_settings
from django.urls import reverse
from mock import patch
from rest_framework import status

from kobo.apps.audit_log.models import AuditAction, AuditLog
from kobo.apps.audit_log.models import AuditLog
from kobo.apps.kobo_auth.shortcuts import User
from kobo.apps.openrosa.apps.main.models import UserProfile
from ...audit_log.audit_actions import AuditAction
from .constants import SOCIALACCOUNT_PROVIDERS


Expand Down
22 changes: 22 additions & 0 deletions kobo/apps/audit_log/audit_actions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from django.db import models


class AuditAction(models.TextChoices):
CREATE = 'create'
DELETE = 'delete'
IN_TRASH = 'in-trash'
PUT_BACK = 'put-back'
REMOVE = 'remove'
UPDATE = 'update'
AUTH = 'auth'
DEPLOY = 'deploy'
ARCHIVE = 'archive'
UNARCHIVE = 'unarchive'
REDEPLOY = 'redeploy'
UPDATE_NAME = 'update-name'
UPDATE_FORM = 'update-form'
UPDATE_SETTINGS = 'update-settings'
UPDATE_QA = 'update-qa'
DISABLE_SHARING = 'disable-sharing'
ENABLE_SHARING = 'enable-sharing'
MODIFY_SHARING = 'modify-sharing'
34 changes: 24 additions & 10 deletions kobo/apps/audit_log/base_views.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
from rest_framework import mixins, viewsets

from kpi.utils.log import logging

def get_nested_field(obj, field: str):
"""
Retrieve a period-separated nested field from an object or dict

Raises an exception if the field is not found
Logs a warning and returns None if the field is not found
"""
split = field.split('.')
attribute = getattr(obj, split[0])
if len(split) > 1:
for inner_field in split[1:]:
if isinstance(attribute, dict):
attribute = attribute.get(inner_field)
else:
attribute = getattr(attribute, inner_field)
return attribute
try:
attribute = getattr(obj, split[0])
if len(split) > 1:
for inner_field in split[1:]:
if isinstance(attribute, dict):
attribute = attribute.get(inner_field)
else:
attribute = getattr(attribute, inner_field)
return attribute
except (AttributeError, KeyError):
logging.warning(f'Attribute not found: {field} on object {obj}')
return None


class AuditLoggedViewSet(viewsets.GenericViewSet):
Expand All @@ -33,6 +37,8 @@ class AuditLoggedViewSet(viewsets.GenericViewSet):
"""

logged_fields = []
log_type = None
model_name = None

def get_object(self):
# actually fetch the object
Expand All @@ -45,12 +51,18 @@ def get_object(self):
value = get_nested_field(obj, field)
audit_log_data[field] = value
self.request._request.initial_data = audit_log_data
self.request._request.log_type = self.log_type
self.request._request.model_name = self.model_name

return obj

def perform_update(self, serializer):
self.perform_update_override(serializer)
audit_log_data = {}
for field in self.logged_fields:
if field == 'data_sharing':
pass

value = get_nested_field(serializer.instance, field)
audit_log_data[field] = value
self.request._request.updated_data = audit_log_data
Expand All @@ -62,6 +74,8 @@ def perform_create(self, serializer):
value = get_nested_field(serializer.instance, field)
audit_log_data[field] = value
self.request._request.updated_data = audit_log_data
self.request._request.log_type = self.log_type
self.request._request.model_name = self.model_name

def perform_destroy(self, instance):
audit_log_data = {}
Expand Down
14 changes: 14 additions & 0 deletions kobo/apps/audit_log/middleware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from kobo.apps.audit_log.models import AuditType, ProjectHistoryLog


def create_project_history_log_middleware(get_response):
def do_thing(request):
response = get_response(request)
if request.method in ['GET', 'HEAD']:
return response
log_type = getattr(request, 'log_type', None)
if log_type == AuditType.PROJECT_HISTORY:
ProjectHistoryLog.create_from_request(request)
return response

return do_thing
73 changes: 73 additions & 0 deletions kobo/apps/audit_log/migrations/0012_alter_auditlog_action.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# Generated by Django 4.2.15 on 2024-10-23 13:32

from django.db import migrations, models


class Migration(migrations.Migration):

replaces = [
('audit_log', '0012_alter_auditlog_action'),
('audit_log', '0013_alter_auditlog_action'),
]

dependencies = [
('audit_log', '0011_projecthistorylog'),
]

operations = [
migrations.AlterField(
model_name='auditlog',
name='action',
field=models.CharField(
choices=[
('create', 'Create'),
('delete', 'Delete'),
('in-trash', 'In Trash'),
('put-back', 'Put Back'),
('remove', 'Remove'),
('update', 'Update'),
('auth', 'Auth'),
('deploy', 'Deploy'),
('archive', 'Archive'),
('unarchive', 'Unarchive'),
('redeploy', 'Redeploy'),
('qa-update', 'Qa Update'),
('sh-disabled', 'Sharing Disabled'),
('sh-enabled', 'Sharing Enabled'),
('sh-modified', 'Sharing Modified'),
],
db_index=True,
default='delete',
max_length=30,
),
),
migrations.AlterField(
model_name='auditlog',
name='action',
field=models.CharField(
choices=[
('create', 'Create'),
('delete', 'Delete'),
('in-trash', 'In Trash'),
('put-back', 'Put Back'),
('remove', 'Remove'),
('update', 'Update'),
('auth', 'Auth'),
('deploy', 'Deploy'),
('archive', 'Archive'),
('unarchive', 'Unarchive'),
('redeploy', 'Redeploy'),
('update-name', 'Update Name'),
('update-form', 'Update Form'),
('update-settings', 'Update Settings'),
('update-qa', 'Update Qa'),
('disable-sharing', 'Disable Sharing'),
('enable-sharing', 'Enable Sharing'),
('modify-sharing', 'Modify Sharing'),
],
db_index=True,
default='delete',
max_length=30,
),
),
]
Loading
Loading