Skip to main content

A reusable django [DRF] application that handles auditing of requests, logins and process

Project description

DRF Audit Trail

A reusable Django DRF application for auditing requests, logins, and custom processes.


Features

  • HTTP request auditing (RequestAuditEvent)
  • Login and logout auditing (LoginAuditEvent)
  • Custom process auditing (ProcessAuditEvent, StepAuditEvent, RegistrationAuditEvent)
  • Integration with SimpleJWT
  • Django Async support
  • Thread safe
  • Error and stacktrace tracking
  • PDF report generation

Installation

pip install drf-audit-trail

Configuration

In your settings.py:

INSTALLED_APPS = [
    ...
    "drf_audit_trail",
]

MIDDLEWARE = [
    ...
    "drf_audit_trail.middleware.RequestLoginAuditEventMiddleware",
]

Database

You can use a separate database for audit data:

DATABASES = {
    "default":  {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
    },
    "audit_trail": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "audit_trail.sqlite3",
    },
}

DRF_AUDIT_TRAIL_DATABASE_ALIAS = "audit_trail"  # Audit database alias
DJANO_DEFAULT_DATABASE_ALIAS = "default"  # Default database alias

DATABASE_ROUTERS = ["drf_audit_trail.database_router.DRFAuditTrail"]

Available Settings

Add to your settings.py as needed:

DRF_AUDIT_TRAIL_REQUEST_AUDIT_URLS = [r"^(?!/admin/jsi18n/).*$"]  # Monitored URLs (regex)
DRF_AUDIT_TRAIL_AUTH_URL = [
    "/api/token/",
    "/admin/login/",
    "/api/logout/",
    "/admin/logout/",
]  # Authentication endpoints
DRF_AUDIT_TRAIL_AUTH_STATUS_CODE_FAILED = 401  # Auth failure status code
DRF_AUDIT_TRAIL_NOTSAVE_REQUEST_BODY_URLS = ['/api/token']  # Endpoints that do not save request body
DRF_AUDIT_TRAIL_USER_PK_NAME = "pk"  # User PK field name

All settings are optional and have sensible defaults.


Audit Models

  • RequestAuditEvent: HTTP request auditing.
  • LoginAuditEvent: Login/logout auditing.
  • ProcessAuditEvent: Custom process auditing.
  • StepAuditEvent: Process step auditing.
  • RegistrationAuditEvent: Execution registration for each step.

Example Usage in a View

from rest_framework.views import APIView
from rest_framework.response import Response

class TestAPIView(APIView):
    def get(self, request, *args, **kwargs):
        drf_request_audit_event = request.META.get("drf_request_audit_event")
        drf_request_audit_event["extra_informations"] = {
            "data": "Example of extra information"
        }
        return Response("ok")

Diagrams

Audit Flow

Flow

ERD

ERD

Middleware Class Diagram

Middleware Class Diagram


Example: Process Auditing

To audit custom business processes, use the process audit utilities:

from drf_audit_trail.models import (
    ProcessAuditEvent,
    RegistrationAuditEvent,
    StepAuditEvent,
)
from drf_audit_trail.process_audit import ProcessAudit


class CreateProductProcessAudit(ProcessAudit):
    def create_process(self) -> ProcessAuditEvent:
        return self.save_model(ProcessAuditEvent(name="Criar produto"))

    def create_steps(self, process: ProcessAuditEvent):
        self.step_validation = self.save_model(
            StepAuditEvent(
                name="Validação dos Dados",
                order=1,
                process=process,
                total_registrations=2,
            )
        )

        self.step_save_db = self.save_model(
            StepAuditEvent(
                name="Salvar no banco de dados",
                order=2,
                process=process,
            )
        )

    def create_registration_step_validation_code(
        self, success, name=None, **extra_fields
    ):
        name = name or "Codigo do produto validados com sucesso"
        return self.save_model(
            RegistrationAuditEvent(
                name=name, step=self.step_validation, success=success, **extra_fields
            )
        )

    def create_registration_step_validation(self, success, name=None, **extra_fields):
        name = name or "Dados de criação validados com sucesso"
        return self.save_model(
            RegistrationAuditEvent(
                name=name, step=self.step_validation, success=success, **extra_fields
            )
        )

    def create_registration_save_db(self, success, name=None, **extra_fields):
        name = name or "Salvar no banco de dados"
        return self.save_model(
            RegistrationAuditEvent(
                step=self.step_save_db, success=success, name=name, **extra_fields
            )
        )


class ProductViewSet(ModelViewSet):
    serializer_class = ProductSerializer
    queryset = Product.objects.all()

    def create(self, request, *args, **kwargs):
        process_audit = CreateProductProcessAudit(request)

        serializer = self.get_serializer(data=request.data)
        if serializer.is_valid():
            process_audit.create_registration_step_validation_code(True)
            process_audit.create_registration_step_validation(True)
        else:
            if serializer.errors.get("code") is not None:
                process_audit.create_registration_step_validation_code(
                    False,
                    "Error de validação de codigo",
                    description=json.dumps(serializer.errors.get("code")),
                )
            validation_errors = json.dumps(serializer.errors)
            process_audit.create_registration_step_validation(
                False, "Erros de validação", description=validation_errors
            )
            raise ValidationError(serializer.errors)

        try:
            self.perform_create(serializer)
            process_audit.create_registration_save_db(True)
        except BaseException as e:
            process_audit.create_registration_save_db(False, e.__str__())
            raise

        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=201, headers=headers)

Handling Long Data and Preventing Database Errors

Starting from version X.X.X, DRF Audit Trail automatically prevents DataError (e.g., StringDataRightTruncation) when saving audit events, even when request parameters (like URLs or query strings) exceed the database limit.

How does it work?

  • Fields sensitive to length, such as url and query_params in the RequestAuditEvent model, use a custom field that automatically truncates values exceeding the database limit (e.g., 2048 characters).
  • When truncation occurs, a warning is logged via Python (drf_audit_trail.truncation), enabling traceability.
  • This ensures the audit middleware never causes a request to fail due to oversized data, making the solution robust for public APIs or endpoints with extensive parameters.

Example of truncation log

WARNING drf_audit_trail.truncation: Truncating value for field 'url' to 2048 characters. Original length: 3010.

Notes

  • Truncation is transparent to the library user.
  • To audit this behavior, set the log level to WARNING in the drf_audit_trail.truncation logger.
  • This behavior applies to all fields of type TruncatingCharField.

License

MIT License


Notes

  • All settings are optional and have default values.
  • For advanced customization, see the code and docstrings.
  • For questions, check the docstrings or open an issue.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

drf_audit_trail-0.4.4.tar.gz (16.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

drf_audit_trail-0.4.4-py3-none-any.whl (24.6 kB view details)

Uploaded Python 3

File details

Details for the file drf_audit_trail-0.4.4.tar.gz.

File metadata

  • Download URL: drf_audit_trail-0.4.4.tar.gz
  • Upload date:
  • Size: 16.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.10.12 Linux/6.17.9-76061709-generic

File hashes

Hashes for drf_audit_trail-0.4.4.tar.gz
Algorithm Hash digest
SHA256 df5d5de3a49b3eaf0fd818adbcdc99dd8289d2babec2fa1f9638406a11180c64
MD5 8904d242765185f4255085633fc71cc3
BLAKE2b-256 1bc8e0aac68750ef093910abac0f028b089682cd8d22045776a4c19de1f5fa6e

See more details on using hashes here.

File details

Details for the file drf_audit_trail-0.4.4-py3-none-any.whl.

File metadata

  • Download URL: drf_audit_trail-0.4.4-py3-none-any.whl
  • Upload date:
  • Size: 24.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.10.12 Linux/6.17.9-76061709-generic

File hashes

Hashes for drf_audit_trail-0.4.4-py3-none-any.whl
Algorithm Hash digest
SHA256 53d76c2999a16afb93a4ebaeb2808a4d86ac5fa46a0657599e16b1be7ab09682
MD5 e473b2691a782916cd08191e8d0d4366
BLAKE2b-256 4cb88b665ca9b7be2420640168de2be800ec7bea3466e46d4b26034d3d5fa0a2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page