django-auditlog/auditlog/management/commands/auditlogflush.py

97 lines
3.1 KiB
Python
Raw Normal View History

import datetime
2017-01-26 19:19:23 +00:00
from django.core.management.base import BaseCommand
from django.db import connection
from auditlog import get_logentry_model
LogEntry = get_logentry_model()
2017-01-26 19:19:23 +00:00
class Command(BaseCommand):
2020-08-31 12:22:50 +00:00
help = "Deletes all log entries from the database."
2020-08-31 12:22:50 +00:00
def add_arguments(self, parser):
2020-12-06 20:29:24 +00:00
parser.add_argument(
"-y",
"--yes",
2020-12-06 20:29:24 +00:00
action="store_true",
default=None,
help="Continue without asking confirmation.",
dest="yes",
)
parser.add_argument(
"-b",
"--before-date",
default=None,
help="Flush all entries with a timestamp before a given date (ISO 8601).",
dest="before_date",
type=datetime.date.fromisoformat,
)
parser.add_argument(
"-t",
"--truncate",
action="store_true",
default=None,
help="Truncate log entry table.",
dest="truncate",
)
2020-08-31 12:22:50 +00:00
def handle(self, *args, **options):
2020-12-06 20:29:24 +00:00
answer = options["yes"]
truncate = options["truncate"]
before = options["before_date"]
if truncate and before:
self.stdout.write(
"Truncate deletes all log entries and can not be passed with before-date."
)
return
2020-09-07 07:10:37 +00:00
if answer is None:
warning_message = (
2020-12-06 20:29:24 +00:00
"This action will clear all log entries from the database."
)
if before is not None:
warning_message = f"This action will clear all log entries before {before} from the database."
self.stdout.write(warning_message)
2020-12-06 20:29:24 +00:00
response = (
input("Are you sure you want to continue? [y/N]: ").lower().strip()
)
answer = response == "y"
if not answer:
self.stdout.write("Aborted.")
return
if not truncate:
entries = LogEntry.objects.all()
if before is not None:
entries = entries.filter(timestamp__date__lt=before)
count, _ = entries.delete()
2020-09-07 07:10:37 +00:00
self.stdout.write("Deleted %d objects." % count)
2020-08-31 12:22:50 +00:00
else:
database_vendor = connection.vendor
database_display_name = connection.display_name
table_name = LogEntry._meta.db_table
if not TruncateQuery.support_truncate_statement(database_vendor):
self.stdout.write(
"Database %s does not support truncate statement."
% database_display_name
)
return
with connection.cursor() as cursor:
query = TruncateQuery.to_sql(table_name)
cursor.execute(query)
self.stdout.write("Truncated log entry table.")
class TruncateQuery:
SUPPORTED_VENDORS = ("postgresql", "mysql", "oracle", "microsoft")
@classmethod
def support_truncate_statement(cls, database_vendor) -> bool:
return database_vendor in cls.SUPPORTED_VENDORS
@staticmethod
def to_sql(table_name) -> str:
return f"TRUNCATE TABLE {table_name};"