feat: 添加审计日志auditlog表

This commit is contained in:
caoqianming 2023-12-07 09:38:24 +08:00
parent d9ddefe5db
commit ba34b26928
6 changed files with 138 additions and 8 deletions

View File

@ -0,0 +1,31 @@
# Generated by Django 3.2.12 on 2023-12-07 01:35
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('monitor', '0003_alter_drfrequestlog_view_method'),
]
operations = [
migrations.CreateModel(
name='AuditLog',
fields=[
('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
('action', models.CharField(max_length=20, verbose_name='动作')),
('model_name', models.CharField(max_length=20, verbose_name='模型名')),
('instance_id', models.CharField(editable=False, max_length=20, verbose_name='记录ID')),
('change_reason', models.CharField(default='', max_length=50, verbose_name='变更原因')),
('change_time', models.DateTimeField(verbose_name='变更时间')),
('val_new', models.JSONField(default=dict, verbose_name='变更后完整数据')),
('difference', models.JSONField(default=list, verbose_name='变更情况')),
('change_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='操作人')),
],
),
]

View File

@ -4,6 +4,19 @@ from django.db import models
from apps.utils.models import BaseModel
class AuditLog(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
action = models.CharField('动作', max_length=20)
model_name = models.CharField('模型名', max_length=20)
instance_id = models.CharField('记录ID', max_length=20, editable=False)
change_reason = models.CharField('变更原因', default='', max_length=50)
change_user = models.ForeignKey(
'system.user', on_delete=models.SET_NULL, verbose_name='操作人', null=True, blank=True)
change_time = models.DateTimeField('变更时间')
val_new = models.JSONField('变更后完整数据', default=dict)
difference = models.JSONField('变更情况', default=list)
class DrfRequestLog(BaseModel):
"""Logs Django rest framework API requests"""
@ -42,7 +55,8 @@ class DrfRequestLog(BaseModel):
response = models.TextField(null=True, blank=True)
errors = models.TextField(null=True, blank=True)
agent = models.TextField(null=True, blank=True)
status_code = models.PositiveIntegerField(null=True, blank=True, db_index=True)
status_code = models.PositiveIntegerField(
null=True, blank=True, db_index=True)
class Meta:
verbose_name = "DRF请求日志"

View File

@ -1,4 +1,14 @@
from rest_framework import serializers
from apps.utils.serializers import CustomModelSerializer
from apps.monitor.models import AuditLog
class DbbackupDeleteSerializer(serializers.Serializer):
filepaths = serializers.ListField(child=serializers.CharField(), label="文件地址列表")
filepaths = serializers.ListField(
child=serializers.CharField(), label="文件地址列表")
class AuditLogSerializer(CustomModelSerializer):
class Meta:
model = AuditLog
fields = '__all__'

View File

@ -1,4 +1,63 @@
import psutil
from apps.monitor.models import AuditLog
from apps.system.models import User
from datetime import datetime
from apps.utils.tools import compare_values
from apps.utils.models import get_model_info
def delete_auditlog(model, instance_id):
"""
删除其对应的审计记录
"""
model_name = get_model_info(model)
AuditLog.objects.filter(model_name=model_name,
instance_id=instance_id).delete()
def create_auditlog(action: str, instance, val_new: dict, val_old: dict = None, change_reason: str = '', delete_time: datetime = None, delete_user: User = None):
"""
生成审计日志
action: create/update/delete/其他action
"""
app_label_model_name = get_model_info(instance)
if val_old is None:
val_old = {}
difference = []
has_changed = False
if action == 'create':
has_changed = True
change_user = instance.create_by
change_time = instance.create_time
elif action == 'delete':
has_changed = True
change_user = delete_user if delete_user else instance.update_by
change_time = delete_time if delete_time else instance.update_time
else:
change_user = instance.update_by
change_time = instance.update_time
for k, v in val_new.items():
if k not in ['create_by', 'update_by', 'create_time', 'update_time', 'id']:
if k not in val_old:
difference.append(
{'field': k, 'action': 'create', 'val_old': None, 'val_new': v})
elif not compare_values(val_new.get(k), val_old.get(k), ignore_order=True):
difference.append(
{'field': k, 'action': 'update', 'val_old': val_old[k], 'val_new': v})
if difference:
has_changed = True
if has_changed:
AuditLog.objects.create(
action=action,
model_name=app_label_model_name,
instance_id=instance.id,
val_new=val_new,
difference=difference,
change_reason=change_reason,
change_user=change_user,
change_time=change_time
)
class ServerService:
@classmethod
@ -17,7 +76,7 @@ class ServerService:
ret['count'] = psutil.cpu_count(logical=False)
ret['percent'] = psutil.cpu_percent(interval=1)
return ret
@classmethod
def get_disk_dict(cls):
ret = {}
@ -29,4 +88,4 @@ class ServerService:
@classmethod
def get_full(cls):
return {'cpu': cls.get_cpu_dict(), 'memory': cls.get_memory_dict(), 'disk': cls.get_disk_dict()}
return {'cpu': cls.get_cpu_dict(), 'memory': cls.get_memory_dict(), 'disk': cls.get_disk_dict()}

View File

@ -1,5 +1,5 @@
from django.urls import path
from .views import DrfRequestLogViewSet, ServerInfoView, LogView, LogDetailView, index, room, video, DbBackupView
from .views import DrfRequestLogViewSet, ServerInfoView, LogView, LogDetailView, index, room, video, DbBackupView, AuditlogViewSet
API_BASE_URL = 'api/monitor/'
HTML_BASE_URL = 'monitor/'
@ -13,5 +13,8 @@ urlpatterns = [
path(API_BASE_URL + 'log/<str:name>/', LogDetailView.as_view()),
path(API_BASE_URL + 'dbbackup/', DbBackupView.as_view()),
path(API_BASE_URL + 'server/', ServerInfoView.as_view()),
path(API_BASE_URL + 'request_log/', DrfRequestLogViewSet.as_view({'get': 'list'}), name='requestlog_view')
path(API_BASE_URL + 'request_log/',
DrfRequestLogViewSet.as_view({'get': 'list'}), name='requestlog_view'),
path(API_BASE_URL + 'auditlog/',
AuditlogViewSet.as_view({'get': 'list'}), name='auditlog_view')
]

View File

@ -7,13 +7,13 @@ from rest_framework.permissions import IsAuthenticated
from django.conf import settings
import os
from rest_framework import serializers
from apps.monitor.serializers import DbbackupDeleteSerializer
from apps.monitor.serializers import DbbackupDeleteSerializer, AuditLogSerializer
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework.exceptions import NotFound
from rest_framework.mixins import ListModelMixin
from apps.monitor.filters import DrfLogFilterSet
from apps.monitor.models import DrfRequestLog
from apps.monitor.models import DrfRequestLog, AuditLog
from apps.monitor.errors import LOG_NOT_FONED
from apps.monitor.services import ServerService
@ -188,3 +188,16 @@ class DrfRequestLogViewSet(ListModelMixin, CustomGenericViewSet):
ordering = ['-requested_at']
filterset_class = DrfLogFilterSet
search_fields = ['path', 'view']
class AuditlogViewSet(ListModelMixin, CustomGenericViewSet):
"""审计日志
审计日志
"""
perms_map = {'get': '*'}
queryset = AuditLog.objects.all()
list_serializer_class = AuditLogSerializer
ordering = ['-change_time']
filterset_fields = ['change_user']
search_fields = ['model_name', 'action']