feat: 添加审计日志auditlog表
This commit is contained in:
parent
d9ddefe5db
commit
ba34b26928
|
@ -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='操作人')),
|
||||
],
|
||||
),
|
||||
]
|
|
@ -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请求日志"
|
||||
|
|
|
@ -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__'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
]
|
||||
|
|
|
@ -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']
|
||||
|
|
Loading…
Reference in New Issue